牛客练习赛14 B 区间倍增ST表

链接: 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值