( ext{感谢 @狸狸养的敏敏 面对面教我ODT 帮他宣传一波(划掉)})
( ext{如果你不会树链剖分 请去模板题。})
( ext{ODT , Old Driver Tree , 就是一种数据结构 你修改越多 这个算法的复杂度越低。})
( ext{操作大概是这个样子的 : 用set 维护 n 个块(n指的是序列长度)})
struct node {
int l ; int r ;
mutable int val ;
bool operator < (const node & x) const {
return l < x.l ;
}
};
set < node > s ;
#define slt set < node > :: iterator
...
n = read() ;
s.insert({1 , n + 1 , 0}) ;
( ext{反正不管 你区间修改的时候就把块合并起来。。})
( ext{所以按照这个思路 我们可以先建一个大块。。因为初始是1-n 都是0})
( ext{然后你在修改之前查询一下区间的值。。修改之后就是 (r - l + 1) * val})
( ext{返回绝对值即可。。})
(mathcal{Code})
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '
') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
struct node {
int l ; int r ;
mutable int val ;
bool operator < (const node & x) const {
return l < x.l ;
}
};
set < node > s ;
#define slt set < node > :: iterator
inline slt Split(int pos) {
slt it = s.lower_bound((node) {pos}) ;
if(it != s.end() && it -> l == pos) return it ;
-- it ;
int l = it -> l ;
int r = it -> r ;
int val = it -> val ;
s.erase(it) ;
s.insert({l , pos - 1 , val}) ;
return s.insert({pos , r , val}).first ;
}
inline int Assign(int l , int r , int val) {
slt it2 = Split(r + 1) ;
slt it1 = Split(l) ;
int sum = 0 ;
int sum2 = (r - l + 1) * val ;
for(slt it = it1 ; it != it2 ; it ++) sum += (it -> r - it -> l + 1) * it -> val ;
s.erase(it1 , it2) ;
s.insert({l , r , val}) ;
return abs(sum - sum2) ;
}
int n ;
struct Node {
int v ;
int nxt ;
};
const int N = 1e5 + 10 ;
Node e[N << 1] ;
int cnt = 0 ;
int head[N] ;
inline void Add(int u , int v) {
e[++ cnt].v = v ;
e[cnt].nxt = head[u] ;
head[u] = cnt ;
return ;
}
int top[N] ;
int id[N] ; int size[N] ;
int d[N] ; int idx = 0 ;
int fa[N] ; int son[N] ;
inline void Dfs1(int u) {
size[u] = 1 ;
for(register int i = head[u] ; i ; i = e[i].nxt ) {
int v = e[i].v ;
if(v == fa[u]) continue ;
d[v] = d[u] + 1 ;
fa[v] = u ;
Dfs1(v) ;
size[u] += size[v] ;
if(size[v] > size[son[u]]) son[u] = v ;
}
return ;
}
inline void Dfs2(int u , int t) {
id[u] = ++ idx ;
top[u] = t ;
if(! son[u]) return ;
Dfs2(son[u] , t) ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if((v ^ fa[u]) && (v ^ son[u])) Dfs2(v , v) ;
}
}
inline int getopt() { string s = "" ;
register char c = getchar() ;
while(isspace(c)) c = getchar() ;
while(! isspace(c)) {
s += c ;
c = getchar() ;
}
if(s == "install") return 1 ;
if(s == "uninstall") return 0 ;
}
inline int Change_Range(int x , int y) {
int fx = top[x] ;
int fy = top[y] ;
int ans = 0 ;
while(fx ^ fy) {
if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
ans += Assign(id[fx] , id[x] , 1) ;
x = fa[fx] ;
fx = top[x] ;
}
if(id[x] > id[y]) swap(x , y) ;
ans += Assign(id[x] , id[y] , 1) ;
return ans ;
}
inline int Uninstall(int x) {
return Assign(id[x] , id[x] + size[x] - 1 , 0) ;
}
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() ;
s.insert({1 , n + 1 , 0}) ;
for(register int i = 2 ; i <= n ; i ++) {
int u = read() ; u ++ ;
Add(u , i) ;
Add(i , u) ;
}
Dfs1(1) ;
Dfs2(1 , 1) ;
for(register int t = read() ; t -- ; ) {
int opt = getopt() ;
if(opt == 1) {
int x = read() ; x ++ ;
write(Change_Range(x , 1)) ;
}
if(opt == 0) {
int x = read() ; x ++ ;
write(Uninstall(x)) ;
}
}
return 0 ;
}