树链剖分,用线段树进行区间维护,对已安装的软件标记为1,未安装的记为0,每次操作时,先查询,再更新。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <bitset>
#define INF 0x3f3f3f3f
#define eps 1e-6
#define PI 3.1415926
#define mod 1000000009
#define base 2333
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int maxx = 1e3 + 10;
inline void splay(int &v) {
v=0;char c=0;int p=1;
while(c<'0' || c >'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int n, v, q, x, len, cnt, head[maxn], fa[maxn], son[maxn];
int siz[maxn], out[maxn], id[maxn], dep[maxn], top[maxn];
struct node {
int to, next;
} e[maxn<<1];
struct Tree {
int l, r, m;
int lazy, val, ze, fr;
void fun(int tmp) {
lazy = tmp;
val = (r-l+1)*tmp;
}
} tr[maxn<<2];
void add(int from, int to) {
e[len].to = to;
e[len].next = head[from];
head[from] = len++;
}
void dfs1(int u, int ff, int deep) {
dep[u] = deep, fa[u] = ff;
son[u] = -1, siz[u] = 1;
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(v == ff) continue;
dfs1(v, u, deep+1);
siz[u] += siz[v];
if(son[u] == -1 || siz[son[u]] < siz[v])
son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++cnt;
if(son[u] != -1) 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]) continue;
dfs2(v, v);
}
out[u] = cnt;
}
void PushUp(int id) {
tr[id].val = tr[id<<1].val+tr[id<<1|1].val;
}
void PushDown(int id) {
if(tr[id].lazy != -1) {
tr[id<<1].fun(tr[id].lazy);
tr[id<<1|1].fun(tr[id].lazy);
tr[id].lazy = -1;
}
}
void build(int id, int l, int r) {
tr[id].l = l, tr[id].r = r, tr[id].lazy = -1;
tr[id].m = (l+r)>>1;
if(l == r)
tr[id].val = 0;
else {
build(id<<1, l, tr[id].m);
build(id<<1|1, tr[id].m+1, r);
PushUp(id);
}
}
void update(int id, int l, int r, int v) {
if(l <= tr[id].l && r >= tr[id].r)
tr[id].fun(v);
else {
PushDown(id);
if(l <= tr[id].m) update(id<<1, l, r, v);
if(r > tr[id].m) update(id<<1|1, l, r, v);
PushUp(id);
}
}
int query(int id, int l, int r, int op) {
if(l <= tr[id].l && r >= tr[id].r) {
if(op) return (tr[id].r-tr[id].l+1)-tr[id].val;
else return tr[id].val;
}
else {
PushDown(id);
int sum = 0;
if(l <= tr[id].m) sum += query(id<<1, l, r, op);
if(r > tr[id].m) sum += query(id<<1|1, l, r, op);
return sum;
}
}
int Find(int u, int v) {
int tp1 = top[u], tp2 = top[v];
int ans = 0;
while(tp1 != tp2) {
if(dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
ans += query(1, id[tp1], id[u], 1);
update(1, id[tp1], id[u], 1);
u = fa[tp1], tp1 = top[u];
}
if(dep[u] > dep[v]) swap(u, v);
ans += query(1, id[u], id[v], 1);
update(1, id[u], id[v], 1);
return ans;
}
void solve() {
splay(n);
memset(head, -1, sizeof(head));
len = cnt = 0;
for(int i = 1; i < n; i++) {
splay(v);
add(i, v), add(v, i);
}
dfs1(0, -1, 1);
dfs2(0, 0);
build(1, 1, n);
splay(q);
char str[20];
while(q--) {
scanf("%s", str);
splay(x);
int ans = 0;
if(str[0] == 'i') {
ans = Find(0, x);
}
else {
ans = query(1, id[x], out[x], 0);
update(1, id[x], out[x], 0);
}
printf("%d\n", ans);
}
}
int main() {
//srand(time(NULL));
//freopen("kingdom.in","r",stdin);
//freopen("kingdom.out","w",stdout);
solve();
}