Description
某天,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 Input
4
1 2 1 1
3
1 1
2 1 1
1 1
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
把每个点像弹到的点连边,显然可得出一棵树。
而x能弹几下显然就是x到树中在序列中最靠右的点的路径的size
可是如果维护森林的话,很难知道这个splay中最大的是哪一个
为了方便把弹飞的都连接到n+1点上,那么x弹的次数就是x到n+1的路径的size-1
查询和修改操作详见代码
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (200000+100) 5 using namespace std; 6 int Father[N],Son[N][2],Size[N],Rev[N]; 7 int n,m,a[N]; 8 9 int Get(int x) {return Son[Father[x]][1]==x;} 10 int Is_root(int x) {return Son[Father[x]][1]!=x && Son[Father[x]][0]!=x;} 11 void Update(int x) {Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;} 12 13 void Rotate(int x) 14 { 15 int wh=Get(x); 16 int fa=Father[x],fafa=Father[fa]; 17 if (!Is_root(fa)) Son[fafa][Son[fafa][1]==fa]=x; 18 Father[fa]=x; Son[fa][wh]=Son[x][wh^1]; 19 Father[x]=fafa; Son[x][wh^1]=fa; 20 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 21 Update(fa); Update(x); 22 } 23 24 void Pushdown(int x) 25 { 26 if (Rev[x] && x) 27 { 28 if (Son[x][0]) Rev[Son[x][0]]^=1; 29 if (Son[x][1]) Rev[Son[x][1]]^=1; 30 swap(Son[x][0],Son[x][1]); 31 Rev[x]=0; 32 } 33 } 34 35 void Push(int x) 36 { 37 if (!Is_root(x)) Push(Father[x]); 38 Pushdown(x); 39 } 40 41 void Splay(int x) 42 { 43 Push(x); 44 for (int fa;!Is_root(x);Rotate(x)) 45 if (!Is_root(fa=Father[x])) 46 Rotate(Get(fa)==Get(x)?fa:x); 47 } 48 49 void Access(int x) {for (int y=0;x;y=x,x=Father[x]) Splay(x),Son[x][1]=y,Update(x);} 50 void Make_root(int x) {Access(x); Splay(x); Rev[x]^=1;} 51 int Find_root(int x) {Access(x); Splay(x); while (Son[x][0]) x=Son[x][0]; return x;} 52 void Link(int x,int y) {Make_root(x); Father[x]=y;} 53 void Cut(int x,int y) {Make_root(x); Access(y); Splay(y); Father[x]=Son[y][0]=0;} 54 void Query(int x) {Make_root(n+1); Access(x); Splay(x); printf("%d ",Size[x]-1);} 55 void Change(int x,int y) {Cut(x,x+a[x]<=n?x+a[x]:n+1); Link(x,x+y<=n?x+y:n+1); a[x]=y;} 56 57 int main() 58 { 59 int opt,x,y; 60 scanf("%d",&n); 61 for (int i=1;i<=n;++i) 62 { 63 scanf("%d",&a[i]); 64 if (i+a[i]<=n) Link(i,i+a[i]); 65 else Link(i,n+1); 66 } 67 scanf("%d",&m); 68 for (int i=1;i<=m;++i) 69 { 70 scanf("%d",&opt); 71 if (opt==1) scanf("%d",&x),Query(x+1); 72 if (opt==2) scanf("%d%d",&x,&y),Change(x+1,y); 73 } 74 }