POJ_2104 K-th Number 【主席树】

一 题面

  K-th Number

二 分析

  第一个主席树的题,感触蛮多吧,几个关键点就是可持久化数据结构,这里的主席树其实就是保留了之前各个版本的权值线段树,然后利用权值线段树和历史版本可以进行相加减的优势,实现了第K小。

三 AC代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int MAXN = 1e5 + 15;
 8 const int N = MAXN * 30;
 9 
10 int n, m, tot, len;
11 int a[MAXN], b[MAXN];
12 int T[N], lson[N], rson[N], sum[N];
13 //进行离散化
14 int getID(int val)
15 {
16     return lower_bound(b + 1, b + n + 1, val) - b;
17 }
18 //初始化,如果追求速度,可以进行优化
19 void build(int &root, int l, int r)
20 {
21     root = tot++;
22     if(l == r)
23         return;
24     sum[root] = 0;
25     int mid = (l + r) >> 1;
26     build(lson[root], l, mid);
27     build(rson[root], mid + 1, r);
28 }
29 //构造新版本的权值线段树
30 void update(int &cur, int pre, int l, int r, int val)
31 {
32     cur = tot++;
33     lson[cur] = lson[pre];
34     rson[cur] = rson[pre];
35     sum[cur] = sum[pre] + 1;
36     if(l == r)  return;
37     int mid = (l + r) >> 1;
38     if(val <= mid)  update(lson[cur], lson[pre], l, mid, val);
39     else    update(rson[cur], rson[pre], mid + 1, r, val);
40 }
41 //询问第K小
42 int query(int x, int y, int l, int r, int k)
43 {
44     if(l == r)
45         return l;
46     int mid = (l + r) >> 1;
47     int res = sum[lson[y]] - sum[lson[x]];
48     if(res >= k)    return query(lson[x], lson[y], l, mid, k);
49     else    return query(rson[x], rson[y], mid + 1, r, k - res);
50 }
51 int main()
52 {
53     scanf("%d %d", &n, &m);
54     for(int i = 1; i <= n; i++)
55     {
56         scanf("%d", &a[i]);
57         b[i] = a[i];
58     }
59     sort(b + 1, b + n + 1);
60     len = unique(b + 1, b + n + 1) - b - 1;
61     tot = 0;
62     build(T[0], 1, len);
63     for(int i = 1; i <= n; i++)
64     {
65         update(T[i], T[i-1], 1, len, getID(a[i])); 
66     }
67     while(m--)
68     {
69         int l, r, k;
70         scanf("%d %d %d", &l, &r, &k);
71         printf("%d\n", b[query(T[l - 1], T[r], 1, len, k)]);
72     }
73     return 0;
74 }

 

posted @ 2019-05-01 21:57  Dybala21  阅读(106)  评论(0编辑  收藏  举报