【CF543E】Listening to Music

【CF543E】Listening to Music

题面

洛谷

题目大意

给你一个长度为\(n\)序列\(a_i\),和一个常数\(m\),定义一个函数\(f(l,x)\)\([l,l+m-1]\)中小于\(x\)的数的个数,有\(q\)个询问,每次给定\(l,r,x\)查询\(min_{i=l}^rf(i,x)\)

题解

先转化一个条件:

小于\(x\)的最小\(=\)大于等于\(x\)的最多

则我们就是要查询大于等于\(x\)的最多

然后再用\(m\)减去即可。

那么怎么做呢?

我们按照权值从大到小将所有位置排序

然后对于每个数,我们设它原位置在\(i\)

将左端点在原位置\(x\)时能覆盖到\(i\)的位置打上标记

依次按照值域建树,每次二分查找到最后一个大于等于查询数的

询问区间最大值即可。

\(tips:\)这题卡空间,要用到一些空间优化。

代码

#include  
#include  
#include  
#include  
#include  
#include  
using namespace std; 
inline int gi() { 
    register int data = 0, w = 1; 
    register char ch = 0; 
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
}
typedef unsigned long long ull; 
#define lson t[o].ls
#define rson t[o].rs
#define lmax (l == mid ? int(lson) : int(t[lson].mx))
#define rmax (mid + 1 == r ? int(rson) : int(t[rson].mx))
const int INF = 1e9;
const int MAX_N = 2e5 + 5; 
struct Node {
    ull mx : 18, ls : 23, rs : 23; 
} t[MAX_N * 40]; 
int tot = 0, rt[MAX_N];
int modify(int p, int l, int r, int ql, int qr) {
    if (l == r) { return p + 1; } 
    int o = ++tot; t[o] = t[p];
    if (ql <= l && r <= qr) return ++t[o].mx, o;
    int mid = (l + r) >> 1, tag = t[o].mx - max(lmax, rmax); 
    if (ql <= mid) lson = modify(t[p].ls, l, mid, ql, qr);
    if (qr > mid) rson = modify(t[p].rs, mid + 1, r, ql, qr);
    t[o].mx = max(lmax, rmax);
    t[o].mx += tag;
    return o; 
}
int query(int o, int l, int r, int ql, int qr) {
    if (l == r) return o; 
    if (ql <= l && r <= qr) return t[o].mx;
    int mid = (l + r) >> 1, res = 0, tag = t[o].mx - max(lmax, rmax);
    if (ql <= mid) res = max(res, query(lson, l, mid, ql, qr));
    if (qr > mid) res = max(res, query(rson, mid + 1, r, ql, qr));
    return res + tag; 
}
int N, M;
pair a[MAX_N]; 
int main () {
    N = gi(), M = gi();
    for (int i = 1; i <= N; i++) a[i].first = 0 - gi(), a[i].second = i;
    sort(&a[1], &a[N + 1]);
    for (int i = 1; i <= N; i++) {
        int ql = max(1, a[i].second - M + 1);
        int qr = min(a[i].second, N - M + 1);
        rt[i] = modify(rt[i - 1], 1, N - M + 1, ql, qr); 
    }
    int Q = gi(), ans = 0;
    while (Q--) {
        int l = gi(), r = gi(), x = gi();
        x ^= ans;
        int id = upper_bound(&a[1], &a[N + 1], make_pair(-x, INF)) - a - 1;
        printf("%d\n", ans = M - query(rt[id], 1, N - M + 1, l, r)); 
    } 
    return 0; 
} 

转载于:https://www.cnblogs.com/heyujun/p/10208715.html

你可能感兴趣的:(数据结构与算法)