题目大意:有一棵树,两个修改
- $install;x:$把根节点到$x$软件路径上的值全部变为$1$,并输出修改的节点个数
- $uninstall;x:$把$x$以及它的子树的值变为$0$,并输出修改的节点个数
题解:树链剖分,比较一下修改前后值的变化,即为答案
卡点:1.边忘记开两倍
C++ Code:
#include <cstdio>
#define maxn 100010
using namespace std;
int n, m;
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
}
int dep[maxn], sz[maxn], fa[maxn];
int dfn[maxn], son[maxn], top[maxn], idx;
void dfs1(int rt) {
sz[rt] = 1;
for (int i = head[rt]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[rt]) {
fa[v] = rt;
dep[v] = dep[rt] + 1;
dfs1(v);
sz[rt] += sz[v];
if (!son[rt] || sz[son[rt]] < sz[v]) son[rt] = v;
}
}
}
void dfs2(int rt) {
dfn[rt] = ++idx;
int v = son[rt];
if (v) top[v] = top[rt], dfs2(v);
for (int i = head[rt]; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa[rt] && v != son[rt]) {
top[v] = v;
dfs2(v);
}
}
}
int V[maxn << 2];
void add(int rt, int l, int r, int L, int R, int op) {
if (L <= l && R >= r) {
V[rt] = (r - l + 1) * op;
return ;
}
if (V[rt] == r - l + 1) {
V[rt << 1] = r - l + 2 >> 1;
V[rt << 1 | 1] = r - l + 1 >> 1;
}
int mid = l + r >> 1;
if (L <= mid) add(rt << 1, l, mid, L, R, op);
if (R > mid) add(rt << 1 | 1, mid + 1, r, L, R, op);
V[rt] = V[rt << 1] + V[rt << 1 | 1];
}
int ask(int rt, int l, int r, int L, int R) {
if (L <= l && R >= r) return V[rt];
if (V[rt] == r - l + 1) {
V[rt << 1] = r - l + 2 >> 1;
V[rt << 1 | 1] = r - l + 1 >> 1;
}
if (V[rt] == 0) V[rt << 1] = V[rt << 1 | 1] = 0;
int mid = l + r >> 1, ans = 0;
if (L <= mid) ans = ask(rt << 1, l, mid, L, R);
if (R > mid) ans += ask(rt << 1 | 1, mid + 1, r, L, R);
return ans;
}
inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
void modify(int x, int y, int num) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
add(1, 1, n, dfn[top[x]], dfn[x], num);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
add(1, 1, n, dfn[x], dfn[y], num);
}
int query(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += ask(1, 1, n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans += ask(1, 1, n, dfn[x], dfn[y]);
return ans;
}
int root = 1;
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int a;
scanf("%d", &a);
add(a + root, i + root);
add(i + root, a + root);
}
dep[top[root] = root] = 1;
dfs1(root);
dfs2(root);
scanf("%d", &m);
while (m --> 0) {
char op[15];
int ans, x;
scanf("%s%d", op, &x); x += root;
if (op[0] == 'i') {
ans = query(root, x);
modify(root, x, 1);
printf("%d
", query(root, x) - ans);
} else {
ans = ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1);
add(1, 1, n, dfn[x], dfn[x] + sz[x] - 1, 0);
printf("%d
", ans - ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1));
}
}
return 0;
}