CF797E Array Queries

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);
        }
    }
}
原文地址:https://www.cnblogs.com/wwlwQWQ/p/14191405.html