主席树模板

模板题:洛谷3834。

  注意:数组至少32倍。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 200010;
inline int qread(){
    register int ch = getchar(), x = 0, flag = 0;
    while(ch < '0' || ch > '9')    {if(ch == '-')    flag = 1;    ch = getchar();}
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
    return flag ? -x : x;
}
int sum[maxn << 5];
int size[maxn << 5];
int ls[maxn << 5];
int rs[maxn << 5];
int rt[maxn];
int data[maxn];
int pl[maxn];
int n, sz, cnt, m;
void build(int &x, int l, int r){
    x = ++cnt;
    sum[x] = 0;
    if(l == r)    return ;
    int mid = (l + r) >> 1;
    build(ls[x], l, mid);
    build(rs[x], mid + 1, r);
}
void update(int &x, int l, int r, int last, int p){
    x = ++cnt;
    ls[x] = ls[last];
    rs[x] = rs[last];
    sum[x] = sum[last] + 1;
    if(l == r)    return ;
    int mid = (l + r) >> 1;
    if(p <= mid)    update(ls[x], l, mid, ls[last], p);
    else            update(rs[x], mid + 1, r, rs[last], p);
}
int query(int a, int b, int l, int r, int k){
    if(l == r)    return l;
    int t = sum[ls[b]] - sum[ls[a]], mid = (l + r) >> 1;
    if(k <= t)    return query(ls[a], ls[b], l, mid, k);
    else        return query(rs[a], rs[b], mid + 1, r, k - t);
}
int main(void){
    n = qread();
    m = qread();
    for(int i = 1; i <= n; ++i)
        pl[i] = data[i] = qread();
    sort(pl + 1, pl + n + 1);
    sz = unique(pl + 1, pl + n + 1) - (pl + 1);
    build(rt[0], 1, sz);
    for(int i = 1; i <= n; ++i)    data[i] = lower_bound(pl + 1, pl + sz + 1, data[i]) - pl;
    for(int i = 1; i <= n; ++i)    update(rt[i], 1, sz, rt[i - 1], data[i]);
    while(m--){
        int x = qread(), y = qread(), k = qread();
        printf("%d\n", pl[query(rt[x - 1], rt[y], 1, sz, k)]);
    }
}

 

posted @ 2018-08-23 15:29  junk_yao  阅读(122)  评论(0编辑  收藏  举报