BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002
题意:加边,删边,查询到根的距离。
#include <bits/stdc++.h> using namespace std; const int maxn = 200010; int ch[maxn][2], pre[maxn], rev[maxn], Next[maxn]; int size[maxn]; bool rt[maxn]; void Update_Rev(int r){ if(!r) return; swap(ch[r][0], ch[r][1]); rev[r] ^= 1; } void push_down(int r){ if(rev[r]){ Update_Rev(ch[r][0]); Update_Rev(ch[r][1]); rev[r] = 0; } } void push_up(int r){ size[r] = size[ch[r][0]]+size[ch[r][1]]+1; } void Rotate(int x){ int y = pre[x], kind = ch[y][1] == x; ch[y][kind] = ch[x][!kind]; pre[ch[y][kind]] = y; pre[x] = pre[y]; pre[y] = x; ch[x][!kind] = y; if(rt[y]) rt[y] = false, rt[x] = true; else ch[pre[x]][ch[pre[x]][1]==y]=x; push_up(y); } void P(int r){ if(!rt[r]) P(pre[r]); push_down(r); } void Splay(int r){ P(r); while(!rt[r]){ int f = pre[r], ff = pre[f]; if(rt[f]) Rotate(r); else if((ch[ff][1]==f)==(ch[f][1]==r)) Rotate(f), Rotate(r); else Rotate(r), Rotate(r); } push_up(r); } int Access(int x){ int y = 0; for(;x;x=pre[y=x]){ Splay(x); rt[ch[x][1]] = true, rt[ch[x][1]=y] = false; push_up(x); } return y; } void mroot(int r){ Access(r); Splay(r); Update_Rev(r); } void link(int u, int v){ mroot(u); pre[u] = v; } void cut(int u, int v){ mroot(u); Splay(v); pre[ch[v][0]] = pre[v]; pre[v] = 0; rt[ch[v][0]] = true; ch[v][0] = 0; push_up(v); } int n, m; int main() { scanf("%d", &n); for(int i=0; i<=n+1; i++){ pre[i]=0; ch[i][0]=ch[i][1]=0; rev[i]=0; rt[i] = true; size[i] = 0; } for(int i=1,t; i<=n; i++){ scanf("%d", &t); t = min(i+t, n+1); pre[i] = Next[i] = t; size[i] = 1; } size[n+1] = 1; scanf("%d", &m); int op, x, y; for(int i=1; i<=m; i++){ scanf("%d%d", &op,&x); x++; if(op==1){ mroot(n+1); Access(x); Splay(x); printf("%d\n", size[ch[x][0]]); } else{ scanf("%d", &y); y = min(x+y,n+1); cut(x,Next[x]); link(x,y); Next[x]=y; } } return 0; }