bzoj 2002 弹飞绵羊 lct裸题
上一次用分块过了, 今天换了一种lct(link-cut tree)的写法。
学lct之前要先学过splay。
lct 简单的来说就是 一颗树, 然后每次起作用的都是其中的某一条链。
所以每次如果需要用到一条链, 就要先 access 一下某个位置, 到root, 将其他的非法的东西抠掉。
并且 一个很大的特点就是 假设现在有u,v2个节点, 存在一条边 u -> v, 那么 u 的 父亲指向 v 但是 v 不一定存在 儿子节点指向 u , 也就是说很多时候是单向边。
然后对于整个lct来说, 他由很多个splay组成的。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch tr[x].son[0] 12 #define rch tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 2e5 + 100; 20 int n, t; 21 struct Node{ 22 int son[2], pre; 23 int sz, is_root; 24 inline void init() { 25 son[1] = son[0] = pre = 0; 26 sz = is_root =1; 27 } 28 }tr[N]; 29 void Push_Up(int x){ 30 if(!x) return ; 31 tr[x].sz = tr[lch].sz + tr[rch].sz + 1; 32 } 33 void rotate(int x){ 34 if(tr[x].is_root) return ; 35 int y = tr[x].pre, z = tr[y].pre; 36 int k = x == tr[y].son[1]; 37 tr[y].son[k] = tr[x].son[k^1]; 38 tr[tr[y].son[k]].pre = y; 39 tr[x].son[k^1] = y; 40 tr[y].pre = x; 41 tr[x].pre = z; 42 if(tr[y].is_root) tr[x].is_root = 1, tr[y].is_root = 0; 43 else tr[z].son[ tr[z].son[1] == y] = x; 44 Push_Up(y); 45 46 } 47 void Splay(int x){ 48 while(!tr[x].is_root){ 49 int y = tr[x].pre, z = tr[y].pre; 50 if(!tr[y].is_root){ 51 if((y == tr[z].son[1]) != ( x == tr[y].son[1])) rotate(y); 52 else rotate(x); 53 } 54 rotate(x); 55 } 56 Push_Up(x); 57 } 58 void access(int x){ 59 int y = 0; 60 do{ 61 Splay(x); 62 tr[rch].is_root = 1; 63 rch = y; 64 tr[rch].is_root = 0; 65 Push_Up(x); 66 y = x; 67 x = tr[x].pre; 68 }while(x); 69 } 70 inline void link(int u, int v){ 71 if(v > n) v = 0; 72 tr[u].pre = v; 73 } 74 inline void cut(int x){ 75 access(x); 76 Splay(x); 77 tr[lch].is_root = 1; 78 tr[lch].pre = 0; 79 lch = 0; 80 Push_Up(x); 81 } 82 inline int Query(int x){ 83 access(x); 84 Splay(x); 85 return tr[lch].sz + 1; 86 } 87 int main(){ 88 scanf("%d", &n); 89 for(int i = 1; i <= n; i++) tr[i].init(); 90 for(int i = 1; i <= n; i++){ 91 scanf("%d", &t); 92 link(i, t+i); 93 } 94 int m, op, x, k; 95 scanf("%d", &m); 96 while(m--){ 97 scanf("%d", &op); 98 if(op == 1) { 99 scanf("%d", &x); 100 printf("%d\n", Query(x+1)); 101 } 102 else { 103 scanf("%d%d", &x, &k); 104 cut(x+1); 105 link(x+1, x+k+1); 106 } 107 } 108 return 0; 109 }