洛谷P2146 [NOI2015]软件包管理器
题目链接
题目分析
对不起我就来水个博客
好像这段时间一直很颓,但是什么事情都不干又良心不安,所以就来颓个树剖。
说正事。
最开始做这个题的时候sb了一下,因为虽然可以当做染色染0和1,不知道怎么统计状态变化的软件包的数量,后来发现我们在线段树上维护的\(sum\)的变化值其实就是这段区间状态变化的软件包的数量,然后我们可以偷个懒不用区间查询,直接输出线段树根节点的\(sum\)变化量即可。
代码
贴一个极致压行的80行代码,第一次10min以内过树剖题,有点感动。
#include <bits/stdc++.h>
#define ls(p) p << 1
#define rs(p) p << 1 | 1
#define N (200000 + 10)
using namespace std;
inline int read() {
int cnt = 0, f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
return cnt * f;
}
int nxt[N], to[N], first[N], tot, n, q, x;
void Add(int x, int y) {nxt[++tot] = first[x], first[x] = tot, to[tot] = y;}
int dep[N], siz[N], father[N], son[N], id[N], top[N], idx;
char ope[20];
void dfs_(int x, int fa) {
dep[x] = dep[fa] + 1, siz[x] = 1, father[x] = fa;
for (register int i = first[x]; i; i = nxt[i]) {
int v = to[i];
if (v == fa) continue;
dfs_(v, x);
siz[x] += siz[v];
if (siz[son[x]] < siz[v]) son[x] = v;
}
}
void dfs__(int x, int tp) {
top[x] = tp, id[x] = ++idx;
if (son[x]) dfs__(son[x], tp);
for (register int i = first[x]; i; i = nxt[i]) {
int v = to[i];
if (!id[v]) dfs__(v, v);
}
}
struct segmentree {
int l, r, sum, tag;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define sum(p) tree[p].sum
#define tag(p) tree[p].tag
}tree[N << 2];
void push_up(int p) {sum(p) = sum(ls(p)) + sum(rs(p));}
void push_rev(int p, int k) {sum(p) = (k ? (r(p) - l(p) + 1) : 0), tag(p) = k;}
void push_down(int p) {
if (tag(p) >= 0) push_rev(ls(p), tag(p)), push_rev(rs(p), tag(p)), tag(p) = -1;
}
void build(int p, int l, int r) {
l(p) = l, r(p) = r;
if (l == r) {tag(p) = -1; return;}
int mid = (l + r) >> 1;
build (ls(p), l, mid), build (rs(p), mid + 1, r);
push_up(p);
}
void modify(int p, int l, int r, int d) {
if (l <= l(p) && r >= r(p)) { push_rev(p, d); return;}
push_down(p);
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) modify (ls(p), l, r, d);
if (r > mid) modify(rs(p), l, r, d);
push_up(p);
}
void Modify(int u, int v, int d) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
modify(1, id[top[u]], id[u], d);
u = father[top[u]];
}
dep[u] < dep[v] ? modify(1, id[u], id[v], d) : modify(1, id[v], id[u], d);
}
signed main() {
n = read();
for (register int i = 2; i <= n; ++i) x = read() + 1, Add(x, i), Add(i, x);
dfs_(1, 0), dfs__(1, 1), build (1, 1, n);
q = read();
for (register int i = 1; i <= q; i++) {
scanf("%s", ope + 1); int ans = sum(1);
x = read() + 1, ope[1] == 'i' ? Modify(x, 1, 1) : modify(1, id[x], id[x] + siz[x] - 1, 0);
printf("%d\n", abs(ans - sum(1)));
}
return 0;
}