牛客练习赛14 B:区间的连续段(倍增打表)

题目传送门
dp[i][j]表示从位置 i 开始分 2^j 段的 结束点+1的位置
再进行倍增打表即可,具体看代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1000000+100;

int dp[maxn][25];
ll sum[maxn];

int main(){

    int n,m;
    ll k;
    scanf("%d%d%lld",&n,&m,&k);
    sum[0]=0;
    for(int i=1;i<=n;i++) scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
    for(int i=0;i<=21;i++) dp[n+1][i]=n+1;
    for(int i=n;i>=1;i--){

        dp[i][0]=upper_bound(sum+1,sum+1+n,sum[i-1]+k)-sum;
        for(int j=1;j<=21;j++) dp[i][j]=dp[dp[i][j-1]][j-1];
    }
    while(m--){

        int l,r;
        scanf("%d%d",&l,&r);
        ll cnt=0;
        for(int i=21;i>=0;i--){

            if(dp[l][i]<=r) cnt+=(1<<i),l=dp[l][i];
        }
        if(dp[l][0]>r) printf("%lld\n",cnt+1);
        else printf("Chtholly\n");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81391014
今日推荐