1. 程式人生 > >【bzoj 4764】彈飛大爺

【bzoj 4764】彈飛大爺

數組 har hide clas etc getc led wap 觀察

Description

自從WC退役以來,大爺是越來越懶惰了。為了幫助他活動筋骨,也是受到了彈飛綿羊一題的啟發,機房的小夥伴們決定齊心合力構造一個下面這樣的序列。這個序列共有N項,每項都代表了一個小夥伴的力量值,如果大爺落到了第i個小夥伴的手裏,那麽第i個小夥伴會把大爺彈到第i+ai個小夥伴手裏,其中ai就是第i個小夥伴的力量值,也就是序列的第i項。然而,因為大爺太沈了,所以有些小夥伴不能撐到鍛(you)煉(xi)結束,所以我們中途會替換一些小夥伴,也就是改變序列的某些項。而且,因為大爺太沈了,所以有些小夥伴不能把大爺扔向前方,而是會把大爺往反方向扔,也就是序列中的一些項會是負的(當然,也可能是零嘍)。現在機智的大爺通過在空中的觀察
,已經知道小夥伴們的所有活動——即初始序列、所有更改操作,他想請你算一算,如果他在某時刻落到了某個位置,那麽他會在幾次彈起之後落到小夥伴序列之外(畢竟摔在地上還是蠻疼的)。

Input

第一行為兩個整數N和M,代表序列長度和操作次數。 第二行為N個整數,代表初始的小夥伴序列。 接下來有M行,每行代表一個操作。 如果這一行的第一個數是1,代表該操作是一個詢問操作,接下來一個數X,代表詢問此時大爺從X處,經過幾次彈起會摔在地上。如果永遠不會摔在地上,請輸出-1。 如果這一行的第一個數是2,代表該操作是一個更改操作,接下來兩個數X,Y,代表將序列的第X項改為Y。 N,M <= 200000 |Ai| < N

Output

對於每次詢問操作,輸出彈起次數或-1。

Sample Input

3 19
1 1 1
1 1
1 2
1 3
2 1 2
1 1
1 2
1 3
2 3 -1
1 1
1 2
1 3
2 2 233
1 1
1 2
1 3
2 2 -233
1 1
1 2
1 3

Sample Output

3
2
1
2
2
1
-1
-1
-1
3
1
2
3
1
2

調了兩天終於A了……萬分感謝czl大爺、cyc大爺和yy大爺。

RE了幾發之後一直調不出來,心態爆炸開始亂搞,然後就WA了。怪我自己沒有理解好寫法。

因為有環,所以需要隱藏環上的一條邊來使其成為森林,hl數組與hr數組即代表隱藏邊的端點。

剩下的直接上代碼……

技術分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=200050;
  6 int n,m,t,u,v,a[N],hl[N],hr[N],st[N];
  7 struct node{int fa,c[2],s;bool rev;}tr[5*N];
  8 int read()
  9 {
 10     int x=0,f=1;char c=getchar();
 11     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 12     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 13     return x*f;
 14 }
 15 bool isroot(int k){return !k||!tr[k].fa||(tr[tr[k].fa].c[0]!=k&&tr[tr[k].fa].c[1]!=k);}
 16 void up(int k){tr[k].s=tr[tr[k].c[0]].s+tr[tr[k].c[1]].s+1;}
 17 void down(int k)
 18 {
 19     int l=tr[k].c[0],r=tr[k].c[1];
 20     if(tr[k].rev)
 21     {
 22         tr[k].rev^=1;tr[l].rev^=1;tr[r].rev^=1;
 23         swap(tr[k].c[0],tr[k].c[1]);
 24     }
 25     if(l)hl[l]=hl[k],hr[l]=hr[k];
 26     if(r)hl[r]=hl[k],hr[r]=hr[k];
 27 }
 28 void rotate(int x)
 29 {
 30     int y=tr[x].fa,z=tr[y].fa,l,r;
 31     if(tr[y].c[0]==x)l=0;else l=1;r=l^1;
 32     if(!isroot(y)){if(tr[z].c[0]==y)tr[z].c[0]=x;else tr[z].c[1]=x;}
 33     tr[x].fa=z;tr[y].fa=x;tr[tr[x].c[r]].fa=y;
 34     tr[y].c[l]=tr[x].c[r];tr[x].c[r]=y;
 35     up(y);up(x);
 36 }
 37 void splay(int x)
 38 {
 39     int top=0;st[++top]=x;
 40     for(int i=x;!isroot(i);i=tr[i].fa)st[++top]=tr[i].fa;
 41     for(int i=top;i;i--)down(st[i]);
 42     while(!isroot(x))
 43     {
 44         int y=tr[x].fa,z=tr[y].fa;
 45         if(!isroot(y))
 46         {
 47             if((tr[y].c[0]==x)^(tr[z].c[0]==y))rotate(x);
 48             else rotate(y);
 49         }
 50         rotate(x);
 51     }
 52 }
 53 void acs(int x)
 54 {
 55     int t=0;
 56     while(x){splay(x);tr[x].c[1]=t;up(x);t=x;x=tr[x].fa;}
 57 }
 58 void mkroot(int x){acs(x);splay(x);tr[x].rev^=1;}
 59 int find(int x){acs(x);splay(x);while(tr[x].c[0])x=tr[x].c[0];return x;}
 60 void link(int x,int y){mkroot(x);tr[x].fa=y;acs(x);splay(x);}
 61 void cut(int x,int y)
 62 {
 63     mkroot(x);acs(y);splay(y);
 64     tr[x].fa=tr[y].c[0]=0;up(y);
 65     hl[x]=hr[x]=hl[y]=hr[y]=0;
 66 }
 67 void xlink(int x,int y)
 68 {
 69     if(find(x)==find(y))hl[y]=x,hr[y]=y;
 70     else link(x,y);
 71 }
 72 void xcut(int x,int y)
 73 {
 74     acs(x);splay(x);int li=hl[x],ri=hr[x];
 75     if(hl[x]==x&&hr[x]==y)hl[x]=hl[y]=hr[x]=hr[y]=0;
 76     else
 77     {
 78         cut(x,y);
 79         if(li&&ri)xlink(li,ri);//劃重點!xlink而不是link。
 80     }
 81 }
 82 int query(int x)
 83 {
 84     mkroot(n+1);acs(x);splay(x);
 85     if(hl[x]&&hr[x])return -1;
 86     return tr[x].s-1;
 87 }
 88 int main()
 89 {
 90     n=read();m=read();
 91     for(int i=1;i<=n+1;i++)tr[i].s=1;
 92     for(int i=1;i<=n;i++)
 93     {
 94         a[i]=read();
 95         if(i+a[i]<=0||i+a[i]>n)link(i,n+1);
 96         else xlink(i,i+a[i]);
 97     }
 98     while(m--)
 99     {
100         t=read();
101         if(t==1)u=read(),printf("%d\n",query(u));
102         else
103         {
104             u=read();v=read();
105             if(u+a[u]<=0||u+a[u]>n)cut(u,n+1);
106             else xcut(u,u+a[u]);
107             if(u+v<=0||u+v>n)link(u,n+1);
108             else xlink(u,u+v);
109             a[u]=v;
110         }
111     }
112     return 0;
113 }
View Code

【bzoj 4764】彈飛大爺