POJ – 2104 K-th Number 主席树基础题

ProLightsfx 2017-7-31 168 7/31

K-th Number 主席树基础题

 Source

My Solution

题意:给出一个数组,每次询问这个数组的区间[L, R]内第k大的数是什么。
主席树基础题

主席树,又称可持久化线段树,是对于数组的每个前缀a[1...i]建立一颗线段树,并且a[1...i]的线段树和a[1...i+1]的线段树的区别是只有树上的一条链不同,所以每次对于一颗新的线段树其实只是添加一条长度为logn的链。
它的核心是寻找公共节点和主席树的加减性。
时间复杂度每次查询和修改都是logn,并且空间复杂度大概是O(nlogn)所以一般开20*MAXN的数组应该没有问题。
这里推荐一篇讲解主席树讲得很好的博客
树状结构之主席树
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 8;

//Chairman_Tree
int tot, sz;
int a[MAXN], b[MAXN], root[20*MAXN], ls[20*MAXN], rs[20*MAXN], sum[20*MAXN];

inline void _build(int &o, int l, int r){
    o = ++ tot;
    sum[o] = 0;
    if(l == r) return;
    int mid = (l + r) >> 1;
    _build(ls[o], l, mid);
    _build(rs[o], mid + 1, r);
}

inline void update(int &o, int l, int r, int last, int p){
    o = ++ tot;
    ls[o] = ls[last];
    rs[o] = rs[last];
    sum[o] = sum[last] + 1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(p <= mid) update(ls[o], l, mid, ls[last], p); else update(rs[o], mid + 1, r, rs[last], p); } inline int _query(int ss, int tt, int l, int r, int k){ if(l == r) return l; int mid = (l + r) >> 1;
    int  cnt = sum[ls[tt]] - sum[ls[ss]];
    if(k <= cnt) return _query(ls[ss], ls[tt], l, mid, k); else return _query(rs[ss], rs[tt], mid + 1, r, k - cnt); } int main() { #ifdef LOCAL freopen("a.txt", "r", stdin); //freopen("a.out", "w", stdout); int T = 1; while(T--){ #endif // LOCAL ios::sync_with_stdio(false); cin.tie(0); int n, m, i, ql, qr, x, ind; cin >> n >> m;
    for(i = 1; i <= n; i++){ cin >> a[i];
        b[i] = a[i];
    }
    sort(b + 1, b + n + 1);
    sz = unique(b + 1, b + n + 1) - (b + 1);
    for(i = 1; i <= n; i++){
        a[i] = lower_bound(b + 1, b + sz + 1, a[i]) - b; //It is based on 1~n..
    }
    tot = 0;
    _build(root[0], 1, sz);
    for(i = 1; i <= n; i++){ update(root[i], 1, sz, root[i-1], a[i]); } while(m--){ cin >> ql >> qr >> x;
        ind = _query(root[ql - 1], root[qr], 1, sz, x);
        cout << b[ind] << "n";
    }


    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}

非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

https://www.prolightsfxjh.com/

Thank you!

                                                                                                                                             ------from ProLightsfx

- THE END -

ProLightsfx

11月15日11:49

最后修改:2024年11月15日
0

非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

共有 0 条评论