牛客练习赛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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
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
#define pll pair
#define pli pair
#define pil pair
#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
void upmax(T& a,S b){if(a
void upmin(T& a,S b){if(a>b) a=b;}
template
void W(T m) {cout << m < 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<= L) {
            R = f[0][R];
            ans ++;
        }
        if(R < L) printf("%d\n", ans);
        else puts("Chtholly");
    }
 
    return 0;
}

你可能感兴趣的:(倍增思想,ST表)