某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
某天,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的情况,你都要输出一个需要的步数,占一行。
LCT模板题。
注意:
本题中的装置编号是从0开始的。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <vector> using namespace std; struct splay { int fa,l,r,size; }a[250000]; bool root[250000]; int n,q; void Push_up(int x) { a[x].size=a[a[x].l].size+a[a[x].r].size+1; } void zig(int x) { int y=a[x].fa; int z=a[y].fa; a[x].fa=z,a[y].fa=x; a[y].l=a[x].r,a[a[x].r].fa=y,a[x].r=y; if (root[y]) root[y]=0,root[x]=1; else { if (y==a[z].l) a[z].l=x; else a[z].r=x; } Push_up(y); } void zag(int x) { int y=a[x].fa; int z=a[y].fa; a[x].fa=z,a[y].fa=x; a[y].r=a[x].l,a[a[x].l].fa=y,a[x].l=y; if (root[y]) root[y]=0,root[x]=1; else { if (y==a[z].l) a[z].l=x; else a[z].r=x; } Push_up(y); } void Splay(int x) { while (!root[x]) { int y=a[x].fa; int z=a[y].fa; if (root[y]) { if (a[y].l==x) zig(x); else zag(x); } else { if (a[z].l==y) { if (x==a[y].l) zig(y),zig(x); else zag(x),zig(x); } else { if (x==a[y].r) zag(y),zag(x); else zig(x),zag(x); } } } Push_up(x); } void Access(int x) { int y=0; while (x!=0) { Splay(x); root[a[x].r]=1; a[x].r=y; root[a[x].r]=0; Push_up(x); y=x; x=a[x].fa; } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&a[i].fa); a[i].fa+=i; if (a[i].fa>n) a[i].fa=n+1; } for (int i=0;i<=n+1;i++) a[i].size=1,root[i]=1; a[0].size=0; scanf("%d",&q); while (q--) { int op,x,k; scanf("%d",&op); if (op==1) { scanf("%d",&x); x++; Access(x); Splay(x); printf("%d\n",a[a[x].l].size); } else { scanf("%d%d",&x,&k); x++; Access(x); Splay(x); a[a[x].l].fa=0; root[a[x].l]=1; a[x].l=0; a[x].size=1; int t=x+k; if (t>n) t=n+1; a[x].fa=t; } } return 0; }
【BZOJ 2002】 [Hnoi2010]Bounce 弹飞绵羊
原文地址:http://blog.csdn.net/regina8023/article/details/41894293