链接:
https://www.nowcoder.com/acm/contest/82/B
来源:牛客网
来源:牛客网
给你一个长为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
题解:利用倍增ST表,f[i][pos], 表示右端点为pos,分割2^i次可以到达的左端点。O(N)预处理出f[0][1-n], 然后nlogn得到
f[i][pos],然后每次利用倍增的思想,每个查询从高往下跳。
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <stack>
#include <string>
#include <string.h>
#include <bitset>
#include <map>
#include <set>
#include <assert.h>
#include <iostream>
#include <unordered_map>
namespace fastIO {
#define BUF_SIZE 10000000
// fread -> read
bool IOerror = 0;
char nc() {
static char buf[BUF_SIZE], *pl = buf + BUF_SIZE, *pr = buf + BUF_SIZE;
if(pl == pr) {
pl = buf;
pr = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pr == pl) {
IOerror = 1;
return -1;
}
}
return *pl++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
typedef long long ll;
typedef long double ld;
#define x0 x0___
#define y0 y0___
#define pb push_back
#define SZ(X) ((int)X.size())
#define mp make_pair
#define fi first
#define se second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define ALL(X) X.begin(),X.end()
#define RALL(X) X.rbegin(),X.rend()
#define rep(i,j,k) for(int i = j;i <= k;i ++)
#define per(i,j,k) for(int i = j;i >= k;i --)
#define mem(a,p) memset(a,p,sizeof(a))
const ll MOD = 1E9 + 7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
ll qmod(ll a,ll b,ll c) {ll res=1;a%=c; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%c;a=a*a%c;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
template<typename T, typename S>
void upmax(T& a,S b){if(a<b) a=b;}
template<typename T, typename S>
void upmin(T& a,S b){if(a>b) a=b;}
template<typename T>
void W(T m) {cout << m <<endl;}
void gettle() {while(1);}
void getre() {int t=0;t/=t;}
const int N = 1E6 + 7;
int a[N];
int f[21][N];
int main()
{
int n, m, k;
read(n);
read(m);
read(k);
for(int sum = 0, last = 0, i = 1;i <= n;i ++) {
read(a[i]);
for(sum += a[i];sum > k;sum -= a[++last]);
f[0][i] = last;
}
int mx;
for(mx = 0;1 << mx <= n;mx ++);
rep (i,1,mx) {
rep (j,1,n) {
f[i][j] = f[i-1][f[i-1][j]];
}
}
while(m --) {
int L,R,ans(0);
read(L);
read(R);
per (i,mx,0) {
if(f[i][R] >= L) {
ans += 1<<i;
R = f[i][R];
}
}
if(R >= L) {
R = f[0][R];
ans ++;
}
if(R < L) printf("%d\n", ans);
else puts("Chtholly");
}
return 0;
}