Link
Solution
和弹飞绵羊有点像,所以想这题可能和分块有什么关系。于是想到按值域来分块。
当 (k) 比较大的时候,容易发现跳的次数就非常少,以至于暴力跳都能过。于是当 (k > sqrt{n}) 的时候,不妨就直接暴力地跳。复杂度 (O(nsqrt{n}))
当 (k) 比较小的时候,也就是 (kleq sqrt{n}),发现这样的 (k) 很少,所以可以直接对每个 (k) 预处理出来从位置 (p) 跳完需要的步数。容易写出方程
[f_{p,k}=f_{p+a_p+k,k}+1
]
那么 (O(nsqrt{n})) 预处理就可以了,每次查询 (O(1))。
#include<stdio.h>
#include<math.h>
#define N 100007
#define M 321
inline int read(){
int x=0,flag=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
int f[N][M],n,a[N],sz;
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
sz=(int)(sqrt(n)+0.5);
for(int i=n;i;i--)
for(int j=1;j<=sz;j++)
if(i+a[i]+j>n) f[i][j]=1;
else f[i][j]=f[i+a[i]+j][j]+1;
int Q=read();
while(Q--){
int p=read(),k=read(),ret=0;
if(k<=sz) printf("%d
",f[p][k]);
else{
while(p<=n) p+=a[p]+k,++ret;
printf("%d
",ret);
}
}
}