【bzoj 2002】弹飞绵羊
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
Sample Output
2
3
唉隔壁都在弹飞大爷了,我还在弹绵羊>_<
分块大法【Time:1472 ms】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int N=200050; 7 int n,m,num,pl,w,bl,cnt; 8 int k[N],be[N],st[N],to[N]; 9 int read() 10 { 11 int x=0,f=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 13 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 14 return x*f; 15 } 16 int ask(int t) 17 { 18 int ans=st[t]; 19 while(to[t]<=n) 20 { 21 t=to[t]; 22 ans+=st[t]; 23 } 24 return ans; 25 } 26 int main() 27 { 28 n=read();bl=sqrt(n); 29 if(n%bl)cnt=n/bl+1; 30 else cnt=n/bl; 31 for(int i=1;i<=n;i++) 32 { 33 k[i]=read(); 34 be[i]=(i-1)/bl+1; 35 } 36 for(int i=n;i>0;i--) 37 { 38 if(be[i]==be[i+k[i]]){st[i]=st[i+k[i]]+1;to[i]=to[i+k[i]];} 39 else {st[i]=1;to[i]=i+k[i];} 40 } 41 m=read(); 42 while(m--) 43 { 44 num=read();pl=read()+1; 45 if(num==1)printf("%d\n",ask(pl)); 46 else 47 { 48 w=read(); 49 k[pl]=w; 50 int l=(be[pl]-1)*bl+1; 51 for(int i=pl;i>=l;i--) 52 { 53 if(be[i]==be[i+k[i]]){st[i]=st[i+k[i]]+1;to[i]=to[i+k[i]];} 54 else {st[i]=1;to[i]=i+k[i];} 55 } 56 } 57 } 58 return 0; 59 }
LCT【Time:1844 ms】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=200050; 6 int n,m,c[N][2],next[N],fa[N],size[N],st[N]; 7 bool rev[N]; 8 int read() 9 { 10 int x=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 13 return x*f; 14 } 15 bool isroot(int k){return c[fa[k]][0]!=k&&c[fa[k]][1]!=k;} 16 void up(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;} 17 void down(int x) 18 { 19 int l=c[x][0],r=c[x][1]; 20 if(rev[x]){rev[x]^=1;rev[l]^=1;rev[r]^=1;swap(c[x][0],c[x][1]);} 21 } 22 void rotate(int x) 23 { 24 int y=fa[x],z=fa[y],l,r; 25 if(c[y][0]==x)l=0;else l=1;r=l^1; 26 if(!isroot(y)){if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;} 27 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 28 c[y][l]=c[x][r];c[x][r]=y; 29 up(y);up(x); 30 } 31 void splay(int x) 32 { 33 int top=0;st[++top]=x; 34 for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i]; 35 for(int i=top;i;i--)down(st[i]); 36 while(!isroot(x)) 37 { 38 int y=fa[x],z=fa[y]; 39 if(!isroot(y)) 40 { 41 if((c[y][0]==x)^(c[z][0]==y))rotate(x); 42 else rotate(y); 43 } 44 rotate(x); 45 } 46 } 47 void acs(int x) 48 { 49 int t=0; 50 while(x){splay(x);c[x][1]=t;t=x;x=fa[x];} 51 } 52 void mkroot(int x) 53 { 54 acs(x);splay(x);rev[x]^=1; 55 } 56 void link(int x,int y) 57 { 58 mkroot(x);fa[x]=y;splay(x); 59 } 60 void cut(int x,int y) 61 { 62 mkroot(x);acs(y);splay(y);c[y][0]=fa[x]=0; 63 } 64 int main() 65 { 66 n=read(); 67 for(int i=1;i<=n;i++) 68 { 69 int x=read(); 70 fa[i]=x+i;size[i]=1; 71 if(fa[i]>n+1)fa[i]=n+1; 72 next[i]=fa[i]; 73 } 74 size[n+1]=1; 75 m=read(); 76 while(m--) 77 { 78 int f=read(); 79 if(f==1) 80 { 81 mkroot(n+1); 82 int x=read()+1; 83 acs(x);splay(x);printf("%d\n",size[c[x][0]]); 84 } 85 else 86 { 87 int x=read()+1,y=read(); 88 int t=min(n+1,x+y); 89 cut(x,next[x]);link(x,t);next[x]=t; 90 } 91 } 92 return 0; 93 }