一个根号分块经典题。
考虑如果我们直接(dp)求的话是(O(n * n))的
我们发现这个dp的复杂度有一维是值域大小。
我们还发现我们其实没有必要把所有的答案都求出来,如果(sqrt n leq k),那么最多不会超过(sqrt n)步,我们完全可以进行暴力。
于是我们只需要处理(k leq sqrt n)的部分,dp的复杂度也变成(O(nsqrt n))了
CF797E Array Queries
#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
#define N 100005
#define B 333
int p[N][B],a[N],n,m;
int main(){
scanf("%d",&n);
for(int i = 1;i <= n;++i)
scanf("%d",&a[i]);
ll b = std::sqrt(n);
for(int i = n;i >= 1;--i)
for(int j = 1;j <= b;++j){
p[i][j] = ((i + j + a[i]) > n) ? 1 : (p[i + j + a[i]][j] + 1);
}
scanf("%d",&m);
while(m -- ){
ll x,y;
scanf("%lld%lld",&x,&y);
if(y <= b)
std::cout<<p[x][y]<<std::endl;
else{
int cnt = 0;
while(x <= n)
x = x + y + a[x],cnt ++ ;
std::cout<<cnt<<std::endl;
}
}
}