洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2146
本题涉及算法:
- 树链剖分;
- 线段树(区间更新及求和,涉及懒惰标记)
然后对于每次 install x ,需要将 x 到 1 的路径上面的点全都置为1。
那么在置为1之前统计一下节点数量 num1,
在置为1之后统计一下节点数量 num2,
答案就是 num2 - num1(当然,也可以通过节点深度 dep[x] 来获得节点数量)。
对于每次 unistall x,需要将 x 为根的子树上面的点全都置为0。
那么在置为0之前统计一下权值为1的节点数量 num1,
在置为0之后统计一下权值为1的节点数量 num2,
答案就是 num1-num2(当然,num2 其实就等于 0)。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
#define INF (1<<29)
const int maxn = 100010;
int fa[maxn],
dep[maxn],
size[maxn],
son[maxn],
top[maxn],
seg[maxn], seg_cnt,
rev[maxn],
n,
sumv[maxn<<2], lazy[maxn<<2];
vector<int> g[maxn];
void dfs1(int u, int p) {
size[u] = 1;
for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
int v = (*it);
if (v == p) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v, u);
size[u] += size[v];
if (size[v] >size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
seg[u] = ++seg_cnt;
rev[seg_cnt] = u;
top[u] = tp;
if (son[u]) dfs2(son[u], tp);
for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
int v = (*it);
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
void push_down(int rt, int len) {
if (lazy[rt] != -1) {
int l_len=len-len/2, r_len = len/2;
lazy[rt<<1] = lazy[rt];
lazy[rt<<1|1] = lazy[rt];
sumv[rt<<1] = lazy[rt] * l_len;
sumv[rt<<1|1] = lazy[rt] * r_len;
lazy[rt] = -1;
}
}
void push_up(int rt) {
sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1];
}
void build(int l, int r, int rt) {
lazy[rt] = -1;
int mid = (l + r) / 2;
if (l == r) {
sumv[rt] = 0;
return;
}
build(lson); build(rson);
push_up(rt);
}
void update(int L, int R, long long v, int l, int r, int rt) {
if (L <= l && r <= R) {
sumv[rt] = (r-l+1) * v;
lazy[rt] = v;
return;
}
push_down(rt, r-l+1);
int mid = (l + r) / 2;
if (L <= mid) update(L, R, v, lson);
if (R > mid) update(L, R, v, rson);
push_up(rt);
}
long long query_sum(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return sumv[rt];
push_down(rt, r-l+1);
int mid = (l + r) / 2;
long long tmp = 0;
if (L <= mid) tmp += query_sum(L, R, lson);
if (R > mid) tmp += query_sum(L, R, rson);
return tmp;
}
int t_ask(int u) {
int res = 0;
while (top[u] != 1) {
res += query_sum(seg[top[u]], seg[u], 1, n, 1);
u = fa[top[u]];
}
res += query_sum(seg[1], seg[u], 1, n, 1);
return res;
}
void t_update(int u) {
while (top[u] != 1) {
update(seg[top[u]], seg[u], 1, 1, n, 1);
u = fa[top[u]];
}
update(seg[1], seg[u], 1, 1, n, 1);
}
int m, x;
string op;
int main() {
cin >> n;
for (int i = 2; i <= n; i ++) {
cin >> x;
g[x+1].push_back(i);
}
dep[1] = fa[1] = 1;
dfs1(1, -1);
dfs2(1, 1);
build(1, n, 1);
cin >> m;
while (m --) {
cin >> op >> x;
x ++;
if (op == "install") {
int num1 = t_ask(x);
t_update(x);
int num2 = t_ask(x);
cout << num2 - num1 << endl;
}
else { // uninstall
int num1 = query_sum(seg[x], seg[x]+size[x]-1, 1, n, 1);
update(seg[x], seg[x]+size[x]-1, 0, 1, n, 1);
int num2 = query_sum(seg[x], seg[x]+size[x]-1, 1, n, 1);
cout << num1 - num2 << endl;
}
}
return 0;
}
作者:zifeiy
洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树的更多相关文章
- 洛谷 P2146 [NOI2015]软件包管理器 解题报告
P2146 [NOI2015]软件包管理器 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- 洛谷 P2146 [NOI2015]软件包管理器 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 输出样例#1: 输入样例#2: 输出样例#2: 说明 说明 思路 AC代码 总结 题面 题目链接 P ...
- 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- 洛谷P2146 [NOI2015]软件包管理器
https://www.luogu.org/problemnew/show/P2146 传送门 简单的树链剖分......维护下当前安装了多少个包......修改后查询下就行了......附上极其丑陋 ...
- 洛谷 P2146 [NOI2015]软件包管理器
真没有想到,这竟然会是一道NOI的原题,听RQY说,这套题是北大出的,北大脑抽认为树剖很难... 只恨没有早学几年OI,只A这一道题也可以出去吹自己一A了NOI原题啊 好了,梦该醒了,我们来看题 以后 ...
- 洛谷 pP2146 [NOI2015]软件包管理器
题目的传送门 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...
- 洛谷 2146 [NOI2015]软件包管理器
[题解] 每个软件只依赖另一个软件,且依赖关系不构成环,那么很容易想到这是树形结构. 我们用1表示以安装,用0表示未安装或已卸载:那么安装一个软件,就是把它到树根的路径上所有的点都改为1:卸载一个软件 ...
- 题解 P2146 [NOI2015]软件包管理器
P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
随机推荐
- 磁力搜索嗅探器装成BT
磁力搜索嗅探器装成BT ague-dht ague-dht 是一个磁力链接嗅探器,它伪装成BT下载客服端,加入DHT网络,嗅探磁力链接.每秒发送1000条请求时,平均3秒收到1次带有infohash的 ...
- SpringCloud 融入 Python - Tornado
前言 该篇文章分享如何将Python Web服务融入到Spring Cloud微服务体系中,并调用其服务,Python Web框架用的是Tornado 构建Python web服务 引入py-eure ...
- from和modelform的用法和介绍
from和modelform的用法和介绍 一 form 1. form的作用 1. 生成HTML代码 2. 帮我们做数据有效性的校验 3. 保留上次输入内容,显示错误提示 2. form组件校验数 ...
- 关于父组件通过v-on接收子组件多个参数的一点研究
写组件的时候遇到一个需求,我需要在子组件向父组件传递信息 this.$emit('myEvent', 信息1, 信息2) 在父组件使用v-on来接收 <my-component @myEvent ...
- [运维]ESXI Web Client 标签: vmware运维服务器 2017-05-28 20:59 597人阅读 评论(9)
ESXI安装完成之后,配置好ip,我们就可以使用了?那么如何使用呢?一般来说有两种方式,一种是安装专门的管理客户端,client端,另一种更加方便,就是使用web client端. 下面来介绍一下es ...
- Gatling初次体验
主要步骤: 1. 利用springboot编写了一个简单的服务jdktest 2.将jdktest利用docker在虚拟机中启动 3.创建一个scala工程,利用gatling提供的DSL编写性能脚本 ...
- golang中特殊的标识符
你会发现在 Go 代码中的几乎所有东西都有一个名称或标识符.另外,Go 语言也是区分大小写的,这与 C 家族中的其它语言相同.有效的标识符必须以字符(可以使用任何 UTF-8 编码的字符或 _)开头, ...
- qt 鼠标拖动窗口放大缩小
// 鼠标拖动 具体实现void mouseMoveEvent(QMouseEvent * pEvent) { if (pEvent->buttons() & Qt::LeftButto ...
- PHP文件载入和载入路径
一.文件载入 所谓的文件的载入,就是指将需要的目标文件的代码载入到当前的位置上,从某种意义上来说,文件载入也是一种流程控制! 文件载入的主要目的是体现网站的分层设计,因为不同的页面有很多相同的区域(相 ...
- @codeforces - 1161F@ Zigzag Game
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 2n 个结点的完全二分图,1~n 在左边,n+1~2n ...