传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4196
【题解】
百年不用算法:树链剖分
刚刚推了一发还是很简单的嘛
在支持子树修改的同时支持链修改。
由于子树肯定是在线段树中连在一坨的所以一样修改。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, Q, a[M], par[M]; int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } int sz[M], mx[M]; inline void dfs1(int x) { int u = 0; sz[x] = 1; for (int i=head[x]; i; i=nxt[i]) { dfs1(to[i]); sz[x] += sz[to[i]]; if(sz[to[i]] > u) { u = sz[to[i]]; mx[x] = to[i]; } } } int top[M], pos[M], DFN, beg[M], end[M]; inline void dfs2(int x, int tp) { beg[x] = pos[x] = ++DFN; top[x] = tp; if(mx[x]) dfs2(mx[x], tp); for (int i=head[x]; i; i=nxt[i]) if(to[i] != mx[x]) dfs2(to[i], to[i]); end[x] = DFN; } struct SMT { int w[M]; int tag[M]; # define ls (x<<1) # define rs (x<<1|1) inline void up(int x) { if(!x) return ; w[x] = w[ls] + w[rs]; } inline void pushtag(int x, int l, int r, int d) { if(!x) return ; w[x] = d*(r-l+1); tag[x] = d; } inline void down(int x, int l, int r) { if(!x) return ; if(tag[x] == -1) return ; int mid = l+r>>1; pushtag(ls, l, mid, tag[x]); pushtag(rs, mid+1, r, tag[x]); tag[x] = -1; } inline void edt(int x, int l, int r, int L, int R, int d) { if(L <= l && r <= R) { pushtag(x, l, r, d); return ; } down(x, l, r); int mid = l+r>>1; if(L <= mid) edt(ls, l, mid, L, R, d); if(R > mid) edt(rs, mid+1, r, L, R, d); up(x); } inline int query(int x, int l, int r, int L, int R, int d) { if(L <= l && r <= R) { if(d == 1) return w[x]; else return r-l+1-w[x]; } down(x, l, r); int mid = l+r>>1, ret = 0; if(L <= mid) ret += query(ls, l, mid, L, R, d); if(R > mid) ret += query(rs, mid+1, r, L, R, d); return ret; } }T; int main() { cin >> n; for (int i=2; i<=n; ++i) { scanf("%d", par+i); ++par[i]; add(par[i], i); } dfs1(1); dfs2(1, 1); // for (int i=1; i<=n; ++i) printf("x = %d, top = %d, pos = %d ", i, top[i], pos[i]); for (int i=1; i<=n*4; ++i) T.w[i] = 0, T.tag[i] = -1; cin >> Q; char str[23]; int x; while(Q--) { scanf("%s%d", str, &x); ++x; if(str[0] == 'i') { // install int t = x, tp, ans = 0; while(1) { tp = top[t]; ans += T.query(1, 1, n, pos[tp], pos[t], 0); if(tp == 1) break; t = par[tp]; } printf("%d ", ans); t = x; while(1) { tp = top[t]; T.edt(1, 1, n, pos[tp], pos[t], 1); if(tp == 1) break; t = par[tp]; } } else { // uninstall // printf("%d %d ", beg[x], end[x]); printf("%d ", T.query(1, 1, n, beg[x], end[x], 1)); T.edt(1, 1, n, beg[x], end[x], 0); } } return 0; }