链接:
来源:牛客网 时间限制:C/C++ 7秒,其他语言14秒 空间限制: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行,每行一个整数,表示答案
示例1
输入
5 5 72 3 2 3 43 34 45 51 52 4
输出
11122
备注:
对于100%的数据,1 <= n , m <= 1000000 , 1 <= ai , k <= 1000000000
这题需要用到倍增算法,倍增博大精深啊。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 const int maxn =1e6+10;10 typedef long long ll;11 ll sum[maxn],f[maxn][22];12 13 int main() {14 ll n,m,k;15 scanf("%lld%lld%lld",&n,&m,&k);16 for (int i=1 ;i<=n ;i++){17 ll x;18 scanf("%lld",&x);19 sum[i]=sum[i-1]+x;20 }21 for (int i=0 ;i<=21 ;i++ ) f[n+1][i]=n+1;22 for (int i=n ;i>=1 ;i-- ) {23 f[i][0]=upper_bound(sum+i,sum+n+1,sum[i-1]+k)-sum;24 for (int j=1 ;j<=21 ;j++) {25 f[i][j]=f[f[i][j-1]][j-1];26 }27 }28 while(m--){29 ll x,y,ans=0;30 scanf("%lld%lld",&x,&y);31 for (int i=21 ;i>=0 ;i--){32 if (f[x][i]<=y) ans+=1< y) printf("%lld\n",ans+1);35 else printf("Chtholly\n");36 }37 return 0;38 }