主席树区间第K大

Posted Schenker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主席树区间第K大相关的知识,希望对你有一定的参考价值。

主席树的实质其实还是一颗线段树, 然后每一次修改都通过上一次的线段树,来添加新边,使得每次改变就改变logn个节点,很多节点重复利用,达到节省空间的目的。

1.不带修改的区间第K大。

HDU-2665 模板题

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define max3(a,b,c) max(a,max(b,c))
12 #define min3(a,b,c) min(a,min(b,c))
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const LL mod = 1e9+7;
16 const int N = 1e5+10;
17 struct Node{
18     int l, r;
19     int num;
20 }tree[N*20];
21 int tot = 0;
22 int root[N];
23 int Rank[N];
24 int b[N];
25 struct N{
26     int a;
27     int id;
28     bool operator < (const N & x) const{
29         return a < x.a;
30     }
31 }A[N];
32 
33 int Build(int l, int r){
34     int now = ++tot;
35     tree[now].num = 0;
36     if(l == r) return now;
37     int m = l+r >> 1;
38     tree[now].l = Build(l,m);
39     tree[now].r = Build(m+1,r);
40     return now;
41 }
42 int update(int pre, int l, int r, int k){
43     int now = ++tot;
44     tree[now].num = 0;
45     tree[now].l = tree[pre].l;
46     tree[now].r = tree[pre].r;
47     if(l < r) {
48         int m = l+r >> 1;
49         if(k <= m) tree[now].l = update(tree[pre].l ,l, m, k);
50         else tree[now].r = update(tree[pre].r, m+1, r, k);
51         tree[now].num = tree[tree[now].l].num + tree[tree[now].r].num;
52     }
53     else tree[now].num = 1;
54     return now;
55 }
56 int query(int u, int v, int l, int r,int k){
57     if(l == r) return l;
58     int m = l+r >> 1;
59     int num1 = tree[tree[v].l].num - tree[tree[u].l].num;
60     if(num1 >= k) return query(tree[u].l, tree[v].l, l, m, k);
61     return query(tree[u].r, tree[v].r, m+1,r,k-num1);
62 }
63 int main(){
64     ///Fopen;
65     int t, n, m;
66     scanf("%d", &t);
67     while(t--){
68         scanf("%d%d", &n, &m);
69         for(int i = 1; i <= n; i++){
70             scanf("%d", &A[i].a);
71             A[i].id = i;
72         }
73         sort(A+1, A+1+n); /// 离散化
74         int t = 0;
75         A[0].a = -1;
76         for(int i = 1; i <= n; i++){
77             if(A[i].a != A[i-1].a) t++, Rank[t] = A[i].a;
78             b[A[i].id] = t;
79         }
80         tot = 0;
81         root[0] = Build(1,t);
82         for(int i = 1; i <= n; i++)
83             root[i] = update(root[i-1], 1, t, b[i]);
84         while(m--){
85             int l, r, k;
86             scanf("%d%d%d", &l, &r, &k);
87             printf("%d\n", Rank[query(root[l-1], root[r],1, t, k)]);
88         }
89     }
90     return 0;
91 }
92 /*
93 1
94 10 1
95 1 4 2 3 5 6 7 8 9 0
96 1 3 2
97 
98 */

 

以上是关于主席树区间第K大的主要内容,如果未能解决你的问题,请参考以下文章

poj2761静态区间第k大

HDU - 5919主席树区间不同数+区间第K大

主席树(静态区间第k大)

主席树 - 查询某区间第 K 大

[poj 2104]主席树+静态区间第k大

zoj 2112 Dynamic Rankings 带修改区间第K大 动态主席树