POJ 2104 & HDU 2665 & POJ 2761 K-th Number (主席树入门题 区间第K大)

来源:互联网 发布:python 调用批处理 编辑:程序博客网 时间:2024/05/21 17:02

题意:给你n个数,m次操作,每次操作询问区间[l, r] 中第K大的数。(n、m <= 1e5)


思路:主席树模板题 (主席树知识:点击打开链接)


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1e5+5;int a[maxn], Hash[maxn];int lson[maxn<<5], rson[maxn<<5], sum[maxn<<5];int T[maxn];int m, n, tot;int build(int l, int r){    int rt = ++tot;    sum[rt] = 0;    if(l < r)    {        int mid = (l+r)/2;        lson[rt] = build(l, mid);        rson[rt] = build(mid+1, r);    }    return rt;}int update(int pre, int l, int r, int x){    int rt = ++tot;    lson[rt] = lson[pre], rson[rt] = rson[pre], sum[rt] = sum[pre]+1;    if(l < r)    {        int mid = (l+r)/2;        if(x <= mid)            lson[rt] = update(lson[pre], l, mid, x);        else            rson[rt] = update(rson[pre], mid+1, r, x);    }    return rt;}int query(int u, int v, int l, int r, int k){    if(l >= r) return l;    int mid = (l+r)/2;    int num = sum[lson[v]]-sum[lson[u]];    if(num >= k)        return query(lson[u], lson[v], l, mid, k);    else        return query(rson[u], rson[v], mid+1, r, k-num);}int main(void){    while(cin >> n >> m)    {        tot = 0;        for(int i = 1; i <= n; i++)        {            scanf("%d", &a[i]);            Hash[i] = a[i];        }        sort(Hash+1, Hash+1+n);        int d = unique(Hash+1, Hash+1+n)-Hash-1;        T[0] = build(1, d);        for(int i = 1; i <= n; i++)        {            int x = lower_bound(Hash+1, Hash+1+d, a[i])-Hash;            T[i] = update(T[i-1], 1, d, x);        }        while(m--)        {            int l, r, k;            scanf("%d%d%d", &l, &r, &k);            int ans = query(T[l-1], T[r], 1, d, k);            printf("%d\n", Hash[ans]);        }    }    return 0;}