分析
本题几乎为裸的树剖,假设初始化所有点权均为1。
对于install而言,是对树链进行操作,直接求相应区间的权值和即可,顺便将区间的点权修改为0;
对于uninstall而言,是对子树进行操作,则ans = size(子树) - sum(子树)即可,顺便将子树的点权修改为1;
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define IL inline
using namespace std;
IL int read()
{
char c=getchar();
int sum=0,k=1;
for(;'0'>c || c>'9';c=getchar())
if(c=='-') k=-1;
for(;'0'<=c && c<='9';c=getchar()) sum=sum*10+c-'0';
return sum*k;
}
const int maxn = 1e5 + 5;
int to[maxn];
int nxt[maxn];
int last[maxn];
int cnt;
IL void add(int u, int v)
{
to[++cnt] = v; nxt[cnt] = last[u]; last[u] = cnt;
}
int lazy[maxn * 3];
int sum[maxn * 3];
int lch[maxn * 3];
int rch[maxn * 3];
IL void pushdown(int p, int len)
{
int k;
if(lch[p])
{
k = lch[p];
lazy[k] = lazy[p];
sum[k] = lazy[p] * (len + 1 >> 1);
}
if(rch[p])
{
k = rch[p];
lazy[k] = lazy[p];
sum[k] = lazy[p] * (len >> 1);
}
lazy[p] = -1;
}
IL void build(int &k, int l, int r)
{
int p = k;
lazy[p] = -1;
if(l == r) { sum[p] = 1; return ; }
int mid = (l + r) >> 1;
lch[p] = ++k; build(k, l, mid);
rch[p] = ++k; build(k, mid + 1, r);
sum[p] = sum[lch[p]] + sum[rch[p]];
}
IL int update(int p, int l, int r, int x, int y, int w)
{
if(l == x && r == y)
{
int s = sum[p];
lazy[p] = w;
sum[p] = w * (r - l + 1);
return s;
}
if(lazy[p] != -1) pushdown(p, r - l + 1);
int mid = (l + r) >> 1;
int ans = 0;
if(y <= mid) ans = update(lch[p], l, mid, x, y, w); else
if(mid < x) ans = update(rch[p], mid + 1, r, x, y, w); else
ans = update(lch[p], l, mid, x, mid, w) + update(rch[p], mid + 1, r, mid + 1, y, w);
sum[p] = sum[lch[p]] + sum[rch[p]];
return ans;
}
int n;
int fa[maxn];
int dep[maxn];
int size[maxn];
int son[maxn];
int top[maxn];
int id[maxn];
IL void dfs1(int u, int f)
{
fa[u] = f;
dep[u] = dep[f] + 1;
size[u] = 1;
for(int i = last[u], v; i; i = nxt[i])
{
v = to[i];
dfs1(v, u);
size[u] += size[v];
if(size[son[u]] < size[v]) son[u] = v;
}
}
IL void dfs2(int u, int topf)
{
id[u] = ++cnt;
top[u] = topf;
if(!son[u]) return ; dfs2(son[u], topf);
for(int i = last[u], v; i; i = nxt[i])
if(to[i] != son[u])
dfs2(to[i], to[i]);
}
IL int swap_(int &x, int &y) { int tmp = x; x = y; y = tmp; }
IL int query(int x, int y)
{
int ans = 0;
for(; top[x] != top[y];)
{
if(dep[top[x]] < dep[top[y]]) swap_(x, y);
ans += update(1, 1, n, id[top[x]], id[x], 0);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap_(x, y);
ans += update(1, 1, n, id[x], id[y], 0);
return ans;
}
int main()
{
n = read();
for(int i = 2; i <= n; ++i) add(read() + 1, i);
dfs1(1, 0);
cnt = 0; dfs2(1, 1);
int k = 1; build(k, 1, n);
char c;
for(int t = read(), x; t; --t)
{
scanf(" %c", &c);
x = read() + 1;
if(c == 'i') printf("%d\n", query(1, x)); else
if(c == 'u') printf("%d\n", size[x] - update(1, 1, n, id[x], id[x] + size[x] - 1, 1));
}
return 0;
}