Bounce(弹走绵羊)
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input第一行包含一个整数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
Output对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input4 1 2 1 1 31 12 1 11 1Sample Output
23
#include#include #include #include #include #include using namespace std;const int maxn = 200000+11;int size[maxn],child[maxn][2],fa[maxn];void pushup(int x){ size[x]=size[child[x][0]]+size[child[x][1]]+1;}bool isroot(int x){ int y=fa[x]; return (child[y][0]!=x&&child[y][1]!=x);}void _rot(int x){ int y=fa[x],w=(child[y][1]==x); int g=fa[y]; if(!isroot(y)){ if(child[g][0]==y)child[g][0]=x; else if(child[g][1]==y)child[g][1]=x; } child[y][w]=child[x][w^1]; fa[child[x][w^1]]=y; child[x][w^1]=y; fa[x]=g; fa[y]=x; pushup(y);}void splay(int x){ while(!isroot(x)){ int y=fa[x],g=fa[y]; if(isroot(y)){ _rot(x); break; } if(!isroot(g))_rot(y); _rot(x); } pushup(x);}void accuss(int x){ int y=0; while(x){ splay(x); child[x][1]=y; pushup(x); y=x; x=fa[x]; }}void cut(int x){ accuss(x); splay(x); int l=child[x][0]; fa[l]=0; child[x][0]=0; pushup(x);}void link(int x,int y){ cut(x); fa[x]=y;}int main(){ int i,j,k,m,n; scanf("%d",&n); for(i=1;i<=n;i++)size[i]=1; for(i=1;i<=n;i++){ int val; scanf("%d",&val); if(i+val>n)fa[i]=0; else fa[i]=i+val; } size[0]=0; scanf("%d",&m); for(i=1;i<=m;i++){ int t; scanf("%d",&t); if(t==1){ int x; scanf("%d",&x); x++; accuss(x); splay(x); printf("%d\n",size[child[x][0]]+1); } else{ int x,y; scanf("%d%d",&x,&y); x++; if(x+y>n)link(x,0); else link(x,x+y); } } return 0;}