区间的连续段~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行,每行一个整数,表示答案

输入例子:
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 ;
}
上一篇:CRF++使用小结(转)


下一篇:The 3n + 1 problem