某天,Lostmonkey發明了一種超級彈力裝置,爲了在他的綿羊朋友面前顯擺,他邀請小綿羊一塊兒玩個遊戲。遊戲一開始,Lostmonkey在地上沿着一條直線擺上\(n\)個裝置,每一個裝置設定初始彈力系數\(k_i\),當綿羊達到第\(i\)個裝置時,它會往前彈\(k_i\)步,達到第\(i+k_i\)個裝置,若不存在第\(i+k_i\)個裝置,則綿羊被彈飛。綿羊想知道當它從第\(i\)個裝置起步時,被彈幾回後會被彈飛。爲了使得遊戲更有趣,Lostmonkey能夠修改某個彈力裝置的彈力系數,任什麼時候候彈力系數均爲正整數。ios
第一行包含一個整數\(n\),表示地上有\(n\)個裝置,裝置的編號從\(0\)到\(n-1\)。
接下來一行有\(n\)個正整數,依次爲那\(n\)個裝置的初始彈力系數。
第三行有一個正整數\(m\)。
接下來\(m\)行每行至少有兩個數\(i,j\),若\(i=1\),你要輸出從\(j\)出發被彈幾回後被彈飛,若\(i=2\)則還會再輸入一個正整數\(k\),表示第\(j\)個彈力裝置的係數被修改爲\(k\)。spa
對於每一個\(i=1\)的狀況,你都要輸出一個須要的步數,佔一行。code
4
1 2 1 1
3
1 1
2 1 1
1 1
排序
2
3
遊戲
對於20%的數據\(n,m\le 10000\);
對於100%的數據\(n\le 200000,m\le 100000\);ip
根爲\(\textbf{n+1}\)get
以樣例作例子:
input
爲蛤哈?
因爲splay是按深度關鍵字排序,因此根的左子樹的大小就是要被彈幾回了呀。io
把原來的邊刪了在連新的不就完了嗎……class
#include<iostream> #include<cstdio> using namespace std; int ch[200002][2],fa[200002],siz[200002],num[200002],lazr[200002],cnt,n,q; inline unsigned rd(){ unsigned re=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){ re=re*10+ch-'0'; ch=getchar(); } return re; } inline bool isroot(int bt){return ch[fa[bt]][0]!=bt&&ch[fa[bt]][1]!=bt;} inline int drct(int bt){return ch[fa[bt]][1]==bt;} inline void pushup(int bt){siz[bt]=siz[ch[bt][0]]+siz[ch[bt][1]]+1;} inline void reverse(int bt){swap(ch[bt][0],ch[bt][1]);lazr[bt]^=1;} inline void pd(int bt){ if(lazr[bt]){ if(ch[bt][0])reverse(ch[bt][0]); if(ch[bt][1])reverse(ch[bt][1]); lazr[bt]=0; } } inline void pushdown(int u){ if(!isroot(u))pushdown(fa[u]); pd(u); } inline void rotate(int u){ int f=fa[u],g=fa[f],c=drct(u); if(!isroot(f))ch[g][drct(f)]=u; fa[u]=g; ch[f][c]=ch[u][c^1]; if(ch[f][c])fa[ch[f][c]]=f; ch[u][c^1]=f; fa[f]=u; pushup(f); pushup(u); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u]))rotate(drct(fa[u])==drct(u)?fa[u]:u); rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int a,int b){ makeroot(a); fa[a]=b; } void cut(int a,int b){ makeroot(a); access(b); splay(b); ch[b][0]=0; fa[a]=0; pushup(b); } int main(){ n=rd(); for(int i=1;i<=n;i++){ num[i]=rd(); siz[i]=1; } for(int i=1;i<=n;i++){ if(i+num[i]<=n)fa[i]=i+num[i]; else fa[i]=n+1; } q=rd(); for(int i=1;i<=q;i++){ int opt=rd(),x=rd()+1; if(opt==1){ makeroot(n+1); access(x); splay(x); printf("%d\n",siz[ch[x][0]]); }else{ int y=rd(); if(x+num[x]<=n)cut(x,x+num[x]); else cut(x,n+1); num[x]=y; if(x+num[x]<=n)link(x,x+num[x]); else link(x,n+1); } } }