CSP/NOIP新赛制内部挑战赛3 B. contest

 

 

 

 

考虑维护一个类似链式的结构,去维护i位置为起点的一组将到哪里,然后一直跳下去就好

想到这里,自然就会考虑到用倍增去优化

 

这个倍增的预处理要从n倒着枚举

因为它都是向后跳的,要先把后面的算出来啊!! WA了两发

 

 

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
int n,t,x,a[maxn],pos[maxn][20];
ll v[maxn][20];
ll sum[maxn];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d%d",&n,&t,&x);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int j=1;
    for(int i=1;i<=n;i++)
        sum[i]=sum[i-1]+a[i];
    for(int i=1;i<=n;i++)
    {
        while(j<n && sum[j]-sum[i-1]<t) j++;
        pos[i][0]=j;
        v[i][0]=j-i+1;
    }
    for(int i=n;i>=1;i--)
        for(int j=1;j<=19;j++)
        {
            if(pos[i][j-1]+x+1>n || !pos[pos[i][j-1]+x+1][j-1]) break;
            pos[i][j]=pos[pos[i][j-1]+x+1][j-1];
            v[i][j]=v[i][j-1]+v[pos[i][j-1]+x+1][j-1];
        }
    int l,r,q;
    ll ans=0; scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        ans=0;
        scanf("%d%d",&l,&r);
        int j=l;
        for(int k=19;k>=0;k--)
        {
            if(j>n) break;
            if(pos[j][k]>r || !pos[j][k]) continue;
            ans+=v[j][k];
            j=pos[j][k]+x+1;
        }
        if(j<=r) ans+=r-j+1;
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2020-11-28 18:16  andyc_03  阅读(117)  评论(0编辑  收藏  举报