主席树模板求不带修改的区间k大

来源:互联网 发布:mysql minpoolsize 编辑:程序博客网 时间:2024/04/26 11:27

现在会主席树是不是晚了点。主席树的牛逼就是公用了节点然后因为类似前缀和(其实可以叫做时间前缀和)所以节点可以拿来相减。然后就十分玄妙了。。。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = (int)3e6 + 10;const int maxn = (int)1e5;int lson[N], rson[N], sum[N];int Time[N], total;int s[N], X[N];void PushUp(int rt){    sum[rt] = sum[lson[rt]] + sum[rson[rt]];}int build(int L, int R){    int now = ++total;    if (L == R){        lson[now] = rson[now] = 0;        sum[now] = 0;        return now;    }    int m = (L + R) >> 1;    lson[now] = build(L, m);    rson[now] = build(m + 1, R);    PushUp(now);    return now;}int update(int rt, int pos, int L, int R){    int now = ++total;    if (L == R){        sum[now] = sum[rt] + 1;        lson[now] = rson[now] = 0;        return now;    }    int m = (L + R) >> 1;    if (pos <= m){        lson[now] = update(lson[rt], pos, L, m);        rson[now] = rson[rt];    }else{        rson[now] = update(rson[rt], pos, m+ 1, R);        lson[now] = lson[rt];    }    PushUp(now);    return now;}int ask(int rt1, int rt2, int k, int L, int R){    if (L == R) return X[L];    int number = sum[lson[rt2]] - sum[lson[rt1]];    int m = (L + R) >> 1;    if (number >= k)        return ask(lson[rt1], lson[rt2], k, L, m);    else        return ask(rson[rt1], rson[rt2], k - number, m +1, R);}int main(){    int cs; scanf("%d", &cs);    int n, m;    while(cs--){        scanf("%d%d", &n, &m);        int cnt = 0;        for (int i = 1; i <= n; i++){            scanf("%d", &s[i]);            X[++cnt] = s[i];        }        sort(X + 1, X + 1 + cnt);        int all = 1;        for (int i = 2; i <= cnt; i++)            if (X[i] != X[i - 1]) X[++all] = X[i];        total = 0;        Time[0] = build(1, all);        for (int i = 1; i <= n; i++){            int pos = lower_bound(X + 1, X + 1 + all, s[i]) - X;            Time[i] = update(Time[i - 1], pos, 1, all);        }        while(m--){            int L, R, k;            scanf("%d%d%d", &L, &R, &k);            printf("%d\n", ask(Time[L - 1], Time[R], k, 1, all));        }    }    return 0;}


0 0
原创粉丝点击