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 }
View Code

 

posted @ 2018-08-14 16:33  Schenker  阅读(88)  评论(0编辑  收藏