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

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

#include
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<r) printf("%lld\n",cnt+1);
		else printf("Chtholly\n");
	}
}

你可能感兴趣的:(牛客网,ACM)