\(\text{感謝 @狸狸養的敏敏 面對面教我ODT 幫他宣傳一波(劃掉)}\)node
\(\text{若是你不會樹鏈剖分 請去模板題。}\)git
\(\text{ODT , Old Driver Tree , 就是一種數據結構 你修改越多 這個算法的複雜度越低。}\)算法
\(\text{操做大概是這個樣子的 : 用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}) ;
\(\text{反正無論 你區間修改的時候就把塊合併起來。。}\)spa
\(\text{因此按照這個思路 咱們能夠先建一個大塊。。由於初始是1-n 都是0}\)code
\(\text{而後你在修改以前查詢一下區間的值。。修改以後就是 (r - l + 1) * val}\)
\(\text{返回絕對值便可。。}\)blog
\(\mathcal{Code}\)get
//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 = '\n') { 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 ; }