本题有多种做法,文章中用的是分块方法
算法大致过程是,记录块内跳到下一块需要几次。
这样修改和查询都是根号n。
/**************************************************************
Problem: 2002
User: 1745073284
Language: C++
Result: Accepted
Time:1996 ms
Memory:3644 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=200000;
int a[maxn],next[maxn],val[maxn],op,x,res,m,n,block;
int main()
{
scanf("%d",&n);
block=floor(sqrt(n));
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=n-1;i>=0;i--)
{
int x=a[i]+i;
if(x>=n) next[i]=-1,val[i]=1;
else if(x>=(i/block+1)*block) next[i]=x,val[i]=1;
else next[i]=next[x],val[i]=val[x]+1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);res=0;
for(int j=x;~j;j=next[j]) res+=val[j];
printf("%d\n",res);
}
else
{
scanf("%d",&x);scanf("%d",&a[x]);
int pos=x/block*block;
for(int j=x;j>=pos;j--)
{
int f=a[j]+j;
if(f>=n) next[j]=-1,val[j]=1;
else if(f>=(j/block+1)*block) next[j]=f,val[j]=1;
else next[j]=next[f],val[j]=val[f]+1;
}
}
}
return 0;
}
/*
4
1 2 1 1
3
1 1
2 1 1
1 1
*/