主席树 hdu2665 Kth number

来源:互联网 发布:网络运营培训 编辑:程序博客网 时间:2024/05/24 06:54

传送门:点击打开链接

题意:区间查询第k大

思路:主席树裸题,原来以前看不懂主席树是因为不懂可持久线段树,要学习主席树,应该先学习可持久线段树,然后再学的,这样主席树就能秒懂了。

主席树就是利用可持久线段树维护前缀和,然后利用前缀和就能查询中间的第k大了。

#include<map>#include<set>#include<cmath>#include<ctime>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iomanip>#include<iostream>#include<algorithm>#include<functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;typedef pair<int, int>PII;const int MX = 5e5 + 5;const int mod = 1e9 + 7;const int INF = 0x3f3f3f3f;int A[MX], B[MX], rear;int S[MX << 2], ls[MX << 2], rs[MX << 2], o[MX], sz;void push_up(int rt) {    S[rt] = S[ls[rt]] + S[rs[rt]];}void build(int l, int r, int &rt) {    rt = ++sz;    if(l == r) {        S[rt] = 0;        return;    }    int m = (l + r) >> 1;    build(l, m, ls[rt]); build(m + 1, r, rs[rt]);    push_up(rt);}void update(int pos, int l, int r, int pre, int &rt) {    rt = ++sz;    if(l == r) {        S[rt] = S[pre] + 1;        return;    }    int m = (l + r) >> 1;    ls[rt] = ls[pre]; rs[rt] = rs[pre];    if(pos <= m) update(pos, l, m, ls[pre], ls[rt]);    else update(pos, m + 1, r, rs[pre], rs[rt]);    push_up(rt);}int query(int k, int l, int r, int pre, int rt) {    if(l == r) return l;    int m = (l + r) >> 1, num = S[ls[rt]] - S[ls[pre]];    if(k <= num) return query(k, l, m, ls[pre], ls[rt]);    else return query(k - num, m + 1, r, rs[pre], rs[rt]);}int main() {    int T, n, m; //FIN;    scanf("%d", &T);    while(T--) {        sz = 0;        scanf("%d%d", &n, &m);        for(int i = 1; i <= n; i++) {            scanf("%d", &A[i]);            B[i] = A[i];        }        sort(B + 1, B + 1 + n);        rear = unique(B + 1, B + 1 + n) - B - 1;        build(1, n, o[0]);        for(int i = 1; i <= n; i++) {            int id = lower_bound(B + 1, B + 1 + rear, A[i]) - B;            update(id, 1, rear, o[i - 1], o[i]);        }        for(int i = 1; i <= m; i++) {            int l, r, k;            scanf("%d%d%d", &l, &r, &k);            int id = query(k, 1, rear, o[l - 1], o[r]);            printf("%d\n", B[id]);        }    }    return 0;}


1 0