题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2002
思路
分块,维护块内一个点在块中跳的步数以及出了这个块后去了哪个点。
暴力维护时,注意要用后面节点跳到的位置,来优化寻找前面节点跳到的位置的过程。
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
const int maxn=200000;
int belong[maxn+10],cnt[maxn+10],to[maxn+10],n,m,ki[maxn+10],size;
int main()
{
scanf("%d",&n);
for(register int i=0; i<n; ++i)
{
scanf("%d",&ki[i]);
}
size=(int)sqrt(n);
for(register int i=0; i<n; ++i)
{
belong[i]=i/size+1;
}
for(register int i=n-1; i>=0; --i)
{
if(i+ki[i]>=n)
{
to[i]=-1;
cnt[i]=1;
}
else if(belong[i+ki[i]]!=belong[i])
{
to[i]=i+ki[i];
cnt[i]=1;
}
else
{
to[i]=to[i+ki[i]];
cnt[i]=cnt[i+ki[i]]+1;
}
}
scanf("%d",&m);
while(m--)
{
int op,a,b;
scanf("%d",&op);
if(op==1)
{
scanf("%d",&a);
int ans=0;
while(a!=-1)
{
ans+=cnt[a];
a=to[a];
}
printf("%d\n",ans);
}
else
{
scanf("%d%d",&a,&b);
ki[a]=b;
for(register int i=a; i>=(belong[a]-1)*size; --i)
{
if(i+ki[i]>=n)
{
to[i]=-1;
cnt[i]=1;
}
else if(belong[i+ki[i]]!=belong[i])
{
to[i]=i+ki[i];
cnt[i]=1;
}
else
{
to[i]=to[i+ki[i]];
cnt[i]=cnt[i+ki[i]]+1;
}
}
}
}
return 0;
}