思想有点妙 …
- 每次安装软件,就把根节点到 x 软件路径上的值全部变为 1
- 同理,每次卸载软件,就把 x 以及它的子树的值变为 0
故我们可以用区间和的思想,每次操作之前记录一下 tr[root].sum
的值,更新之后再查询一遍 tr[root].sum
的值,两者之差的绝对值则为答案。
然后注意一下细节,比如 lazy
更新完以后要么是 0
要么是 1
,所以判断的时候和普通不一样;还有因为实际根节点是从 0
开始的,线段树我的根节点是从 1
开始的,所以要注意每次调用要想清楚到底调用的是实际的还是线段树的。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
int n;
int a[N], head[N];
struct Edge {
int to, next;
}e[N << 1];
int cnt = 0;
void add(int u, int v) {
e[++ cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
//---------
int fa[N], dep[N], son[N], size[N];
void dfs1(int u, int f, int depth) {
fa[u] = f;
dep[u] = depth;
size[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v != f) {
dfs1(v, u, depth + 1);
size[u] += size[v];
if (son[u] == -1 || size[son[u]] < size[v])
son[u] = v;
}
}
}
int tim = 0;
int top[N], tid[N], Rank[N];
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++ tim;
Rank[tim] = u;
if (son[u] == -1) return ;
dfs2(son[u], tp);
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v != fa[u] && v != son[u])
dfs2(v, v);
}
}
//----------
struct Node {
int sum, lazy;
}tr[N << 2];
void pushup(int i) { tr[i].sum = tr[i << 1].sum + tr[i << 1 | 1].sum; }
void pushdown(int i, int l, int r) {
if (tr[i].lazy != -1) {
tr[i << 1].lazy = tr[i].lazy;
tr[i << 1 | 1].lazy = tr[i].lazy;
ll mid = (l + r) >> 1;
tr[i << 1].sum = tr[i].lazy * (mid - l + 1);
tr[i << 1 | 1].sum = tr[i].lazy * (r - mid);
tr[i].lazy = -1;
}
}
void build(int i, int l, int r) {
tr[i].lazy = -1;
if (l == r) tr[i].sum = 0;
else {
ll mid = (l + r) >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
pushup(i);
}
}
void update(int i, int l, int r, int ql, int qr, int x) {
if (ql > r || qr < l) return ;
if (ql <= l && r <= qr) {
tr[i].sum = (r - l + 1) * x;
tr[i].lazy = x;
} else {
pushdown(i, l, r);
ll mid = (l + r) >> 1;
update(i << 1, l, mid, ql, qr, x);
update(i << 1 | 1, mid + 1, r, ql, qr, x);
pushup(i);
}
}
//----------
void query(int u, int v, int x) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
update(1, 1, n, tid[top[u]], tid[u], x);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
update(1, 1, n, tid[u], tid[v], x);
}
int main() {
memset(son, -1, sizeof(son));
int a;
scanf("%d", &n);
for (int i = 1; i < n; i ++)
scanf("%d", &a), add(a, i);
dfs1(0, 0, 1), dfs2(0, 0);
build(1, 1, n);
int q;
scanf("%d", &q);
while (q --) {
char c[10]; int x;
cin >> c; scanf("%d", &x);
int t1 = tr[1].sum;
if (c[0] == 'i') {
query(0, x, 1);
int t2 = tr[1].sum;
printf("%d\n", abs(t2 - t1));
} else if (c[0] == 'u') {
update(1, 1, n, tid[x], tid[x] + size[x] - 1, 0);
int t2 = tr[1].sum;
printf("%d\n", abs(t2 - t1));
}
}
return 0;
}