这里有一篇博客讲的很好
模板(以点权为主): (这个主要是树链剖分的板子, 套的其他数据结构没写)
int n, cnt, head[maxn], tim;
int dep[maxn], siz[maxn], fa[maxn];
int son[maxn], top[maxn], a[maxn];
int tid[maxn], out[maxn], pos[maxn];
struct node {
int to, next, w;
}e[maxn<<1];
void add(int u, int v, int w) {
e[cnt] = node{v, head[u], w};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
}
if (dep[x] > dep[y]) swap(x, y);
ans += query_sum(1, tid[x], tid[y]);
return ans;
}
ll get_max(int x, int y) {
ll mx = -inf;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
mx = max(mx, query_max(1, tid[top[x]], tid[x]));
}
if (dep[x] > dep[y]) swap(x, y);
mx = max(mx, query_max(1, tid[x], tid[y]));
return mx;
}
void add_val(int x, int y, ll val) {
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, tid[top[x]], tid[x], val);
}
if (dep[x] > dep[y]) swap(x, y);
update(1, tid[x], tid[y], val);
}
int get_lca(int x, int y) {
for (;top[x] != top[y]; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
Query on a tree
树链剖分(权值在边上)[修改某条边权, 询问树上路径的最大边权]:
(我把询问两点之间的和的函数一起加进去了,这个就当是权值在边上的综合板子吧)
const int maxn = 1e5 + 5;
ll a[maxn];
int tid[maxn], out[maxn], pos[maxn];
struct Tree {
int tl, tr; ll mx, lazy, val;
void fun(ll tmp) {
lazy = tmp;
mx = val = tmp;
}
}tre[maxn<<2];
void pushup(int id) {
tre[id].mx = max(tre[id<<1].mx, tre[id<<1|1].mx);
tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
}
void pushdown(int id) {
if(tre[id].lazy) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = 0;
}
}
void build(int id, int l, int r) {
tre[id].tl = l; tre[id].tr = r; tre[id].lazy = 0;
if(l == r) {
tre[id].mx = tre[id].val = a[pos[l]];
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur, ll val) {
int l = tre[id].tl, r = tre[id].tr;
if(ul <= l && r <= ur) {
tre[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(ul <= mid) update(id<<1, ul, ur, val);
if(ur > mid) update(id<<1|1, ul, ur, val);
pushup(id);
}
ll query_max(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].mx;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_max(id<<1, ql, qr);
else if(ql > mid) return query_max(id<<1|1, ql, qr);
else return max(query_max(id<<1, ql, mid), query_max(id<<1|1, mid+1, qr));
}
ll query_sum(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].val;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_sum(id<<1, ql, qr);
else if(ql > mid) return query_sum(id<<1|1, ql, qr);
else return query_sum(id<<1, ql, mid) + query_sum(id<<1|1, mid+1, qr);
}
int n, m, cnt, head[maxn], tim;
int siz[maxn], top[maxn];
int son[maxn], dep[maxn], fa[maxn];
int dd[maxn], dis[maxn]; // 表示把那条边换到哪个点上.
struct node {
int to, next, w, idx;
}e[maxn<<1];
void add(int u, int v, int w, int id) {
e[cnt] = node{v, head[u], w, id};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dd[e[i].idx] = to;//把边权强制加到这条边向下的那个点上.
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_max(int x, int y) {
ll mx = -inf;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
mx = max(mx, query_max(1, tid[top[x]], tid[x]));
}
if (dep[x] == dep[y]) return mx; //唯一的不同点,下面的这些代码,其他的还是一样 !!!
if (dep[x] > dep[y]) swap(x, y);
if (tid[son[x]] > tid[y]) swap(x, y);
mx = max(mx, query_max(1, tid[son[x]], tid[y]));
return mx;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
}
if (dep[x] == dep[y]) return ans;
if (dep[x] > dep[y]) swap(x, y);
if (tid[son[x]] > tid[y]) swap(x, y);
ans += query_sum(1, tid[son[x]], tid[y]);
return ans;
}
ll val[maxn];
void solve() {
scanf("%d", &n); init();
for (int i = 1 ; i < n ; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w, i); add(v, u, w, i);
val[i] = 1ll*w; //同时还要记录下每条边的权值方便下面做转化.
}
dfs1(1, -1, 0); dfs2(1, 1);
for (int i = 1 ; i < n ; i ++) {
a[dd[i]] = val[i];
}
build(1, 1, n);
char op[10];
while(1) {
scanf("%s", op);
if (op[0] == 'D') break;
int l, r;
scanf("%d%d", &l, &r);
if (op[0] == 'Q') {
printf("%lld\n", get_max(l, r));
}
else update(1, tid[dd[l]], tid[dd[l]], r);
}
}
洛谷P3384
树链剖分(权值在点上) [区间修改(加值还要去mod) 询问区间和]:
const int maxn = 1e5 + 5;
ll a[maxn], mod;
int tid[maxn], out[maxn], pos[maxn];
struct Tree {
int tl, tr; ll val, mx, lazy;
void fun(ll tmp) {
lazy = (lazy + tmp) % mod;
val = (val + (tr - tl + 1) * tmp) % mod;
mx = tmp;
}
}tre[maxn<<2];
void pushup(int id) {
tre[id].val = tre[id<<1].val+tre[id<<1|1].val;
}
void pushdown(int id) {
if(tre[id].lazy) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = 0;
}
}
void build(int id,int l,int r) {
tre[id].tl = l; tre[id].tr = r; tre[id].lazy = 0;
if(l == r) {
tre[id].val = a[pos[l]] % mod;
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur, ll val) {
int l = tre[id].tl, r = tre[id].tr;
if(ul <= l && r <= ur) {
tre[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(ul <= mid) update(id<<1, ul, ur, val);
if(ur > mid) update(id<<1|1, ul, ur, val);
pushup(id);
}
ll query_sum(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].val % mod;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_sum(id<<1, ql, qr);
else if(ql > mid) return query_sum(id<<1|1, ql, qr);
else return (query_sum(id<<1, ql, mid) + query_sum(id<<1|1, mid+1, qr) % mod);
}
int n, m, cnt, head[maxn], tim, rt;
int siz[maxn], top[maxn];
int son[maxn], dep[maxn], fa[maxn];
struct node {
int to, next, w;
}e[maxn<<1];
void add(int u, int v, int w) {
e[cnt] = node{v, head[u], w};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
ans %= mod;
}
if (dep[x] > dep[y]) swap(x, y);
ans += query_sum(1, tid[x], tid[y]);
return ans % mod;
}
void add_val(int x, int y, ll val) {
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, tid[top[x]], tid[x], val);
}
if (dep[x] > dep[y]) swap(x, y);
update(1, tid[x], tid[y], val);
}
void solve() {
scanf("%d%d%d%lld", &n, &m, &rt, &mod);
init();
for (int i = 1 ; i <= n ; i ++) scanf("%lld", a+i);
for (int i = 1 ; i < n ; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v, 1); add(v, u, 1);
}
dfs1(rt, -1, 0); dfs2(rt, rt); build(1, 1, n);
while(m--) {
int op, x, y; ll z;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%lld", &x, &y, &z);
add_val(x, y, z%mod);
}
else if (op == 2) {
scanf("%d%d", &x, &y);
printf("%lld\n", get_sum(x, y) % mod);
}
else if (op == 3) {
scanf("%d%lld", &x, &z);
update(1, tid[x], out[x], z);
}
else {
scanf("%d", &x);
printf("%lld\n", query(1, tid[x], out[x]) % mod);
}
}
}
BZOJ-1036
树链剖分(权值在点上)[单点修改 询问区间和/最大值]:
const int maxn = 1e5 + 5;
ll a[maxn];
int tid[maxn], out[maxn], pos[maxn];
struct Tree {
int tl, tr; ll val, mx, lazy;
void fun(ll tmp) {
lazy = tmp;
val = (tr - tl + 1) * tmp;
mx = tmp;
}
}tre[maxn<<2];
void pushup(int id) {
tre[id].val = tre[id<<1].val+tre[id<<1|1].val;
tre[id].mx = max(tre[id<<1].mx, tre[id<<1|1].mx);
}
void pushdown(int id) {
if(tre[id].lazy) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = 0;
}
}
void build(int id,int l,int r) {
tre[id].tl = l; tre[id].tr = r; tre[id].lazy = 0;
if(l == r) {
tre[id].val = tre[id].mx = a[pos[l]];
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur, ll val) {
int l = tre[id].tl, r = tre[id].tr;
if(ul <= l && r <= ur) {
tre[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(ul <= mid) update(id<<1, ul, ur, val);
if(ur > mid) update(id<<1|1, ul, ur, val);
pushup(id);
}
ll query_sum(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].val;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_sum(id<<1, ql, qr);
else if(ql > mid) return query_sum(id<<1|1, ql, qr);
else return query_sum(id<<1, ql, mid) + query_sum(id<<1|1, mid+1, qr);
}
ll query_max(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].mx;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_max(id<<1, ql, qr);
else if(ql > mid) return query_max(id<<1|1, ql, qr);
else return max(query_max(id<<1, ql, mid), query_max(id<<1|1, mid+1, qr));
}
int n, m, cnt, head[maxn], tim, rt;
int siz[maxn], top[maxn];
int son[maxn], dep[maxn], fa[maxn];
struct node {
int to, next, w;
}e[maxn<<1];
void add(int u, int v, int w) {
e[cnt] = node{v, head[u], w};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
}
if (dep[x] > dep[y]) swap(x, y);
ans += query_sum(1, tid[x], tid[y]);
return ans;
}
ll get_max(int x, int y) {
ll mx = -inf;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
mx = max(mx, query_max(1, tid[top[x]], tid[x]));
}
if (dep[x] > dep[y]) swap(x, y);
mx = max(mx, query_max(1, tid[x], tid[y]));
return mx;
}
void add_val(int x, int y, ll val) {
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, tid[top[x]], tid[x], val);
}
if (dep[x] > dep[y]) swap(x, y);
update(1, tid[x], tid[y], val);
}
int get_lca(int x, int y) {
for (;top[x] != top[y]; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
void solve() {
scanf("%d", &n); init();
for (int i = 1 ; i < n ; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v, 1); add(v, u, 1);
}
dfs1(1, -1, 0);
dfs2(1, 1);
for (int i = 1 ; i <= n ; i ++) {
scanf("%lld", a+i);
}
build(1, 1, n);
scanf("%d", &m);
while(m--) {
char op[10]; int l, r;
scanf("%s", op);
if (!strcmp(op, "QMAX")) {
scanf("%d%d", &l, &r);
printf("%d\n", get_max(l, r));
}
else if (!strcmp(op, "QSUM")) {
scanf("%d%d", &l, &r);
printf("%d\n", get_sum(l, r));
}
else if (!strcmp(op, "CHANGE")) {
scanf("%d%d", &l, &r);
update(1, tid[l], tid[l], r);
}
}
}
bzoj - 4034
树链剖分(权值在点上)[单点/区间修改(加值) 询问区间和]:
const int maxn = 1e5 + 5;
ll a[maxn];
int tid[maxn], out[maxn], pos[maxn];
struct Tree {
int tl, tr; ll val, lazy;
void fun(ll tmp) {
lazy += tmp;
val += (tr - tl + 1) * tmp;
}
}tre[maxn<<2];
void pushup(int id) {
tre[id].val = tre[id<<1].val+tre[id<<1|1].val;
}
void pushdown(int id) {
if(tre[id].lazy != 0) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = 0;
}
}
void build(int id,int l,int r) {
tre[id].tl = l; tre[id].tr = r; tre[id].lazy = 0;
if(l == r) {
tre[id].val = a[pos[l]];
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur, ll val) {
int l = tre[id].tl, r = tre[id].tr;
if(ul <= l && r <= ur) {
tre[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(ul <= mid) update(id<<1, ul, ur, val);
if(ur > mid) update(id<<1|1, ul, ur, val);
pushup(id);
}
ll query_sum(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].val;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_sum(id<<1, ql, qr);
else if(ql > mid) return query_sum(id<<1|1, ql, qr);
else return query_sum(id<<1, ql, mid) + query_sum(id<<1|1, mid+1, qr);
}
int n, m, cnt, head[maxn], tim, rt;
int siz[maxn], top[maxn];
int son[maxn], dep[maxn], fa[maxn];
struct node {
int to, next, w;
}e[maxn<<1];
void add(int u, int v, int w) {
e[cnt] = node{v, head[u], w};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
}
if (dep[x] > dep[y]) swap(x, y);
ans += query_sum(1, tid[x], tid[y]);
return ans;
}
void add_val(int x, int y, ll val) {
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, tid[top[x]], tid[x], val);
}
if (dep[x] > dep[y]) swap(x, y);
update(1, tid[x], tid[y], val);
}
void solve() {
scanf("%d%d", &n, &m); init();
for (int i = 1 ; i <= n ; i ++) {
scanf("%lld", a+i);
}
for (int i = 1 ; i < n ; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v, 1); add(v, u, 1);
}
dfs1(1, -1, 0); dfs2(1, 1); build(1, 1, n);
while(m--) {
int op, l, r;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &l, &r);
update(1, tid[l], tid[l], r);
}
else if (op == 2) {
scanf("%d%d", &l, &r);
update(1, tid[l], out[l], r);
}
else {
scanf("%d", &l);
printf("%lld\n", get_sum(1, l));
}
}
}
bzoj - 4196
树链剖分(权值在点上)[区间修改(覆盖) 询问区间和]:
const int maxn = 1e5 + 5;
int n, cnt, head[maxn], tim;
int dep[maxn], siz[maxn], fa[maxn];
int son[maxn], top[maxn], a[maxn];
int tid[maxn], out[maxn], pos[maxn];
struct Tree {
int tl, tr, val, lazy;
void fun(int tmp) {
lazy = tmp;
val = (tr - tl + 1) * tmp;
}
}tre[maxn<<2];
void pushup(int id) {
tre[id].val = tre[id<<1].val+tre[id<<1|1].val;
}
void pushdown(int id) {
if(tre[id].lazy != -1) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = -1;
}
}
void build(int id,int l,int r) {
tre[id].tl = l; tre[id].tr = r;
tre[id].lazy = -1; tre[id].val = 0;
if(l == r) return ;
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur, ll val) {
int l = tre[id].tl, r = tre[id].tr;
if(ul <= l && r <= ur) {
tre[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(ul <= mid) update(id<<1, ul, ur, val);
if(ur > mid) update(id<<1|1, ul, ur, val);
pushup(id);
}
ll query_sum(int id, int ql, int qr) {
int l = tre[id].tl , r = tre[id].tr;
if(ql <= l && r <= qr) {
return tre[id].val;
}
pushdown(id);
int mid = (l+r) >> 1 ;
if(qr <= mid) return query_sum(id<<1, ql, qr);
else if(ql > mid) return query_sum(id<<1|1, ql, qr);
else return query_sum(id<<1, ql, mid) + query_sum(id<<1|1, mid+1, qr);
}
struct node {
int to, next, w;
}e[maxn<<1];
void add(int u, int v, int w) {
e[cnt] = node{v, head[u], w};
head[u] = cnt++;
}
void init() {
cnt = 0; Fill(head, -1);
tim = 0; Fill(son, -1);
}
void dfs1(int u, int f, int deep) {
dep[u] = deep + 1; siz[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == f) continue;
fa[to] = u;
dfs1(to, u, deep+1);
siz[u] += siz[to];
if (son[u] == -1 || siz[to] > siz[son[u]]) {
son[u] = to;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
tid[u] = ++tim;
pos[tim] = u;
if (son[u] == -1) {
out[u] = tim;
return ;
}
dfs2(son[u], tp);
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to != son[u] && to != fa[u]) {
dfs2(to, to);
}
}
out[u] = tim;
}
ll get_sum(int x, int y) {
ll ans = 0;
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query_sum(1, tid[top[x]], tid[x]);
}
if (dep[x] > dep[y]) swap(x, y);
ans += query_sum(1, tid[x], tid[y]);
return ans;
}
void add_val(int x, int y, ll val) {
for (;top[x] != top[y] ; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, tid[top[x]], tid[x], val);
}
if (dep[x] > dep[y]) swap(x, y);
update(1, tid[x], tid[y], val);
}
int get_lca(int x, int y) {
for (;top[x] != top[y]; x = fa[top[x]]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
void solve() {
scanf("%d", &n); init();
for (int i = 2 ; i <= n ; i ++) {
int x; scanf("%d", &x);
++x; add(x, i, 1);
}
dfs1(1, -1, 0); dfs2(1, 1); build(1, 1, n);
int m; scanf("%d", &m);
while(m--) {
char op[12]; int x;
scanf("%s%d", op, &x); ++ x;
if (op[0] == 'i') {
int t1 = get_sum(1, x);
add_val(1, x, 1);
printf("%d\n", get_sum(1, x) - t1);
}
else {
printf("%d\n", query_sum(1, tid[x], out[x]));
update(1, tid[x], out[x], 0);
}
}
}