链接:https://www.nowcoder.com/acm/contest/82/B
来源:牛客网
时间限制:C/C++ 7秒,其他语言14秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给你一个长为n的序列a和一个常数k
有m次询问,每次查询一个区间[l,r]内所有数最少分成多少个连续段,使得每段的和都 <= k
如果这一次查询无解,输出"Chtholly"
输入描述:
第一行三个数n,m,k
第二行n个数表示这个序列a
之后m行,每行给出两个数l r表示一次询问
输出描述:
输出m行,每行一个整数,表示答案
输入例子:
5 5 7
2 3 2 3 4
3 3
4 4
5 5
1 5
2 4
输出例子:
1
1
1
2
2
-->
示例1
输入
5 5 7
2 3 2 3 4
3 3
4 4
5 5
1 5
2 4
输出
1
1
1
2
2
备注:
对于100%的数据,1 <= n , m <= 1000000 , 1 <= ai , k <= 1000000000
这题需要用到倍增算法,倍增博大精深啊。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std; const int maxn =1e6+;
typedef long long ll;
ll sum[maxn],f[maxn][]; int main() {
ll n,m,k;
scanf("%lld%lld%lld",&n,&m,&k);
for (int i= ;i<=n ;i++){
ll x;
scanf("%lld",&x);
sum[i]=sum[i-]+x;
}
for (int i= ;i<= ;i++ ) f[n+][i]=n+;
for (int i=n ;i>= ;i-- ) {
f[i][]=upper_bound(sum+i,sum+n+,sum[i-]+k)-sum;
for (int j= ;j<= ;j++) {
f[i][j]=f[f[i][j-]][j-];
}
}
while(m--){
ll x,y,ans=;
scanf("%lld%lld",&x,&y);
for (int i= ;i>= ;i--){
if (f[x][i]<=y) ans+=<<i,x=f[x][i];
}
if (f[x][]>y) printf("%lld\n",ans+);
else printf("Chtholly\n");
}
return ;
}