区间的连续段~ST表(模板题)

链接:https://www.nowcoder.com/acm/contest/82/B
来源:牛客网

时间限制: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 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

这题需要用到倍增算法,倍增博大精深啊。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<queue>
 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<<i,x=f[x][i];
33         }
34         if (f[x][0]>y) printf("%lld
",ans+1);
35         else printf("Chtholly
");
36     }
37     return 0;
38 }
原文地址:https://www.cnblogs.com/qldabiaoge/p/8728277.html