2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 12641 Solved: 6433
[ Submit][ Status][ Discuss]
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
3
HINT
Source
#include <stdio.h>
#include <math.h>
int read()
{
int res=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9'){res=res*10+c-'0';c=getchar();}
return res;
}
int ans,len,n,a[200005],blk[200005],stp[200005],nxt[200005],m,x,y,z;
int main()
{
len=sqrt(n=read());
for(int i=1;i<=n;i++) a[i]=read();
for(int i=n;i>=1;i--)
{
blk[i]=(i-1)/len+1;
if(i+a[i]>n) stp[i]=1,nxt[i]=0;
else if(blk[i+a[i]]>blk[i]) stp[i]=1,nxt[i]=i+a[i];
else stp[i]=stp[i+a[i]]+1,nxt[i]=nxt[i+a[i]];
}
m=read();
for(int i=1;i<=m;i++)
{
x=read();y=read()+1;
if(x==1)
{
ans=0;
while(y)
{
ans+=stp[y];
y=nxt[y];
}
printf("%d\n",ans);
}
else
{
a[y]=(z=read());
for(int i=blk[y]*len;i>(blk[y]-1)*len;i--)
{
if(i+a[i]>n) stp[i]=1,nxt[i]=0;
else if(blk[i+a[i]]>blk[i]) stp[i]=1,nxt[i]=i+a[i];
else stp[i]=stp[i+a[i]]+1,nxt[i]=nxt[i+a[i]];
}
}
}
}
其实这题分块比LCT跑得快。。。