主席树入门

来源:互联网 发布:淘宝运营职位 编辑:程序博客网 时间:2024/06/09 08:32

好久不写博客了有那么一丝小尴尬2333今天队友在旁边做题我没好意思混,又去看了看以前跟来神一起看过教学视频的主席树,感觉有点意思于是就学会了2333不过我原来的线段树风格交的时候MLE了QWQ我还特地把风格改成我那样的,感觉很爆炸。

那么主席树是什么呢,他的本质是棵线段树,好了不BB了反正网上那么多写的比我好的定义为啥要看我的呢2333。反正这玩意支持历史版本查询。我就做了一题查询区间第K大,poj2104。

这个数据结构一开始没懂怎么做,就是因为还在按线段树的模式套。线段树的递归是下标乘2进左子树,乘2+1进右子树,那个时候想不明白啊,我链出去了,那这个关系就没有了我怎么找呢。还好我最近学了splay,我再看视屏的时候感觉他的建树应该是跟splay一样建一棵父亲指向儿子的树。每次更新会产生一个新的根节点,由这个根节点一部分连在未改变的部分,一部分是自己更新的部分,就直接搞上去了很刺激。然后查询哪个版本,就从哪个版本的根进去,去查询就可以了。

K-th Number
Time Limit: 20000MS Memory Limit: 65536K
Total Submissions: 58217 Accepted: 20162
Case Time Limit: 2000MS
Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.
That is, given an array a[1…n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: “What would be the k-th number in a[i…j] segment, if this segment was sorted?”
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2…5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.
Input

The first line of the input file contains n — the size of the array, and m — the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).
The second line contains n different integer numbers not exceeding 109 by their absolute values — the array for which the answers should be given.
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).
Output

For each question output the answer to it — the k-th number in sorted a[i…j] segment.
Sample Input

7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output

5
6
3
Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;//thanks to pyf ...//thanks to qhl ...const int N = 1e5 + 7;struct Tree{    int lt, rt, sum;} t[N * 40];int root[N];int cnt = 0;void cp(Tree &x, Tree y){    x.lt = y.lt, x.rt = y.rt, x.sum = y.sum;}void update(int l, int r, int &x, int y, int k){    cnt ++;    cp(t[cnt], t[y]);    t[cnt].sum ++;    x = cnt;    if (l == r)        return;    int mid = (l + r) / 2;    if (k <= mid)        update(l, mid, t[x].lt, t[y].lt, k);    else        update(mid + 1, r, t[x].rt, t[y].rt, k);}int query(int l, int r, int lt, int rt, int k){    if (l == r)        return l;    int sum = t[t[rt].lt].sum - t[t[lt].lt].sum;    int mid = (l + r) / 2;    if (sum >= k)        return query(l, mid, t[lt].lt, t[rt].lt, k);    else        return query(mid + 1, r, t[lt].rt, t[rt].rt, k - sum);}int a[N], v[N];int get_id(int x, int num){    return lower_bound(v + 1, v + 1 + num, x) - v;}int main(){    int n, q;    while (scanf("%d%d", &n, &q) == 2)    {        for (int i = 1; i <= n; i++)        {            scanf("%d", a + i);            v[i] = a[i];        }        sort(v + 1, v + 1 + n);        int num = unique(v + 1, v + n + 1) - v;        for (int i = 1; i <= n; i++)            update(1, n, root[i], root[i - 1], get_id(a[i], num));        for (int i = 0; i < q; i++)        {            int x, y, z;            scanf("%d%d%d", &x, &y, &z);            printf("%d\n", v[query(1, n, root[x - 1], root[y], z)]);        }    }}