BZOJ2002[Hnoi2010]彈飛綿羊
阿新 • • 發佈:2018-10-05
開始 con zoj pushd spa link 100% aps lin
1 2 1 1
3
1 1
2 1 1
1 1
3 當跳過n之後就被彈飛,那麽可以建一個虛點n+1,將彈飛看作彈到n+1這個節點上。 i會被彈到i+ki號節點上,那麽直接將i號節點和i+ki號節點連上就好了。 修改直接斷開原來連的邊,重新連接一條邊,LCT維護就好了。 因為每個點只會連接一個比它編號大的點,所以最後形成了一棵樹,每次詢問直接查詢j和n+1路徑上的節點數-1即可。
題目描述
某天,Lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力系數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ki個裝置,則綿羊被彈飛。綿羊想知道當它從第i個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,Lostmonkey可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。
輸入
第一行包含一個整數n,表示地上有n個裝置,裝置的編號從0到n-1,接下來一行有n個正整數,依次為那n個裝置的初始彈力系數。第三行有一個正整數m,接下來m行每行至少有兩個數i、j,若i=1,你要輸出從j出發被彈幾次後被彈飛,若i=2則還會再輸入一個正整數k,表示第j個彈力裝置的系數被修改成k。對於20%的數據n,m<=10000,對於100%的數據n<=200000,m<=100000
輸出
對於每個i=1的情況,你都要輸出一個需要的步數,占一行。
樣例輸入
41 2 1 1
3
1 1
2 1 1
1 1
樣例輸出
23 當跳過n之後就被彈飛,那麽可以建一個虛點n+1,將彈飛看作彈到n+1這個節點上。 i會被彈到i+ki號節點上,那麽直接將i號節點和i+ki號節點連上就好了。 修改直接斷開原來連的邊,重新連接一條邊,LCT維護就好了。 因為每個點只會連接一個比它編號大的點,所以最後形成了一棵樹,每次詢問直接查詢j和n+1路徑上的節點數-1即可。
#include<set> #include<map> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m; int x,y; int opt; int s[200020][2]; int f[200020]; int r[200020]; int st[200020]; int size[200020]; int dis[200020]; int get(int rt) { return rt==s[f[rt]][1]; } void pushup(int rt) { size[rt]=size[s[rt][0]]+size[s[rt][1]]+1; } void pushdown(int rt) { if(r[rt]) { r[s[rt][0]]^=1; r[s[rt][1]]^=1; r[rt]^=1; swap(s[rt][0],s[rt][1]); } } int is_root(int rt) { return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1]; } void rotate(int rt) { int fa=f[rt]; int anc=f[fa]; int k=get(rt); if(!is_root(fa)) { s[anc][get(fa)]=rt; } s[fa][k]=s[rt][k^1]; f[s[fa][k]]=fa; s[rt][k^1]=fa; f[fa]=rt; f[rt]=anc; pushup(fa); pushup(rt); } void splay(int rt) { int top=0; st[++top]=rt; for(int i=rt;!is_root(i);i=f[i]) { st[++top]=f[i]; } for(int i=top;i>=1;i--) { pushdown(st[i]); } for(int fa;!is_root(rt);rotate(rt)) { if(!is_root(fa=f[rt])) { rotate(get(fa)==get(rt)?fa:rt); } } } void access(int rt) { for(int x=0;rt;x=rt,rt=f[rt]) { splay(rt); s[rt][1]=x; pushup(rt); } } void reverse(int rt) { access(rt); splay(rt); r[rt]^=1; } int find(int rt) { access(rt); splay(rt); while(s[rt][0]) { rt=s[rt][0]; } return rt; } void link(int x,int y) { reverse(x); f[x]=y; } void cut(int x,int y) { reverse(x); access(y); splay(y); s[y][0]=f[x]=0; } int main() { scanf("%d",&n); for(int i=1;i<=n+1;i++) { size[i]=1; } for(int i=1;i<=n;i++) { scanf("%d",&x); dis[i]=x; if(i+x<=n) { link(i,i+x); } else { link(i,n+1); } } scanf("%d",&m); while(m--) { scanf("%d",&opt); if(opt==1) { scanf("%d",&x); x++; reverse(x); access(n+1); splay(n+1); printf("%d\n",size[n+1]-1); } else { scanf("%d%d",&x,&y); x++; if(x+dis[x]<=n) { cut(x,x+dis[x]); } else { cut(x,n+1); } dis[x]=y; if(x+dis[x]<=n) { link(x,x+dis[x]); } else { link(x,n+1); } } } }
BZOJ2002[Hnoi2010]彈飛綿羊