BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊

n<=200000个点,从i会跳到$i+num_i$,保证$num_i>0$,m<=100000个两种操作:一、修改一个$num$;二、问从$i$开始跳多少步跳出这个序列。

大概是LCT的模板题了。

记住access操作,不停的旋完把右子树腾给儿子。其他可以自行推。

  1 #include<string.h>
  2 #include<stdlib.h>
  3 #include<stdio.h>
  4 #include<math.h>
  5 //#include<assert.h>
  6 #include<algorithm> 
  7 //#include<iostream>
  8 //#include<bitset>
  9 using namespace std;
 10 
 11 int n,m;
 12 #define maxn 200011
 13 struct LCT
 14 {
 15     struct Node
 16     {
 17         int fa,son[2];
 18         bool rev;
 19         int size,realroot;
 20     }a[maxn];
 21     void makeatree(int id)
 22     {
 23         a[id].fa=a[id].son[0]=a[id].son[1]=a[id].rev=0;
 24         a[id].size=1; a[id].realroot=id;
 25     }
 26     void up(int x)
 27     {
 28         if (!x) return;
 29         int &p=a[x].son[0],&q=a[x].son[1];
 30         a[x].size=a[p].size+a[q].size+1;
 31     }
 32     void revsingle(int x)
 33     {
 34         if (!x) return;
 35         a[x].rev^=1;
 36         int &p=a[x].son[0],&q=a[x].son[1];
 37         p^=q; q^=p; p^=q;
 38     }
 39     void down(int x)
 40     {
 41         int &p=a[x].son[0],&q=a[x].son[1];
 42         if (a[x].rev) {revsingle(p); revsingle(q); a[x].rev=0;}
 43         a[p].realroot=a[q].realroot=a[x].realroot;
 44     }
 45     int sta[maxn];
 46     void download(int x)
 47     {
 48         int top=0,i; for (i=x;!isroot(i);i=a[i].fa) sta[++top]=i; sta[++top]=i;
 49         for (;top;top--) down(sta[top]);
 50     }
 51     bool isroot(int x)
 52     {
 53         if (a[x].fa==0) return 1;
 54         return (a[a[x].fa].son[0]!=x && a[a[x].fa].son[1]!=x);
 55     }
 56     void rotate(int x)
 57     {
 58         const int y=a[x].fa,z=a[y].fa;
 59         bool w=(x==a[y].son[0]);
 60         a[x].fa=z;
 61         if (!isroot(y)) a[z].son[y==a[z].son[1]]=x;
 62         a[y].son[w^1]=a[x].son[w];
 63         if (a[x].son[w]) a[a[x].son[w]].fa=y;
 64         a[x].son[w]=y;
 65         a[y].fa=x;
 66         up(y); up(z);
 67     }
 68     void splay(int x)
 69     {
 70         if (!x) return;
 71         download(x);
 72         while (!isroot(x))
 73         {
 74             const int y=a[x].fa,z=a[y].fa;
 75             if (!isroot(y))
 76             {
 77                 if ((y==a[z].son[0])^(x==a[y].son[0])) rotate(x);
 78                 else rotate(y);
 79             }
 80             rotate(x);
 81         }
 82         up(x);
 83     }
 84     void access(int x)
 85     {
 86         int y=0,tmp=x;
 87         while (x) {splay(x); a[x].son[1]=y; up(x); y=x; x=a[x].fa;}
 88         splay(tmp);
 89     }
 90 //    int findroot(int x)
 91 //    {
 92 //        access(x);
 93 //        int y=x;
 94 //        while (a[y].son[0]) {down(y); y=a[y].son[0];}
 95 //        return y;
 96 //    }
 97     void resetroot(int x)
 98     {
 99         access(x);
100         revsingle(x);
101     }
102     void link(int x,int y)
103     {
104         resetroot(x);
105         a[x].fa=y;
106         a[x].realroot=a[y].realroot;
107     }
108     void cut(int x,int y)
109     {
110         resetroot(x);
111         access(y);
112         a[y].son[0]=a[x].fa=0;
113         up(y); a[x].realroot=x;
114     }
115     int query(int x)
116     {
117         access(x);
118         int y=a[x].realroot;
119         resetroot(y);
120         access(x);
121         return a[a[x].son[0]].size+1;
122     }
123 //    void test()
124 //    {
125 //        for (int i=1;i<=n;i++) cout<<i<<" size"<<a[i].size<<" realroot"<<a[i].realroot<<" rev"
126 //        <<a[i].rev<<" son0 "<<a[i].son[0]<<" son1 "<<a[i].son[1]<<" fa "<<a[i].fa<<endl;
127 //        cout<<endl;
128 //    }
129 }t;
130 
131 int num[maxn];
132 int main()
133 {
134     scanf("%d",&n);
135     for (int i=1;i<=n;i++) t.makeatree(i);
136     for (int i=1;i<=n;i++)
137     {
138         scanf("%d",&num[i]);
139         if (i+num[i]<=n) t.link(i,i+num[i]);
140     }
141     scanf("%d",&m);
142     int x,y,z;
143     while (m--)
144     {
145         scanf("%d%d",&x,&y); y++;
146         if (x==1) printf("%d\n",t.query(y));
147         else
148         {
149             scanf("%d",&z);
150             if (y+num[y]<=n) t.cut(y,y+num[y]);
151             num[y]=z;
152             if (y+z<=n) t.link(y,y+z);
153         }
154     }
155     return 0;
156 }
View Code

 

posted @ 2018-01-15 19:47  Blue233333  阅读(162)  评论(0编辑  收藏  举报