主席树区间第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 */

原文地址:https://www.cnblogs.com/MingSD/p/9056815.html

时间: 2024-10-09 01:35:09

主席树区间第K大的相关文章

POJ 2104 K-th Number 主席树 区间第K大

今天第一次接触可持久化数据结构,还是有必要总结一下的. 首先对于查找第k大的问题,先搞清楚怎么样通过利用N颗线段树来求解.如果是求全局第K大,那么可以把数字的值作为位置插入线段树,然后通过区间和+二分来找到第k个位置.因为是通过区间和来找第k大的,显然是满足前缀和性质的,所以查询l,r区间的第k打,就直接根据1-l - 1,1-r两个区间建立两颗线段树,然后通过节点依次相减来求得第k大值.所以这样子解需要的内存空间是n*n*logn的(不需要管数的范围,范围再大也可以通过离散化缩小到n). 但是

HDU 6278 主席树(区间第k大)+二分

Just h-index Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 438    Accepted Submission(s): 203 Problem Description The h-index of an author is the largest h where he has at least h papers wit

zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

zoj2112 主席树动态第k大 (主席树&amp;&amp;树状数组)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

可持久化线段树 区间第k大

2018-04-04 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1175 一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,第K大的数是多少. 例如: 1 7 6 3 1.i = 1, j = 3,k = 2,对应的数为7 6 3,第2大的数为6. Input 第1行:1个数N,表示序列的长度.(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列中

zoj2112 主席树动态第k大 ( 参考资料链接)

参考链接: http://blog.csdn.net/acm_cxlove/article/details/8565309 http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html http://seter.is-programmer.com/posts/31907.html http://blog.csdn.net/metalseed/article/details/8045038

ZOJ2112--Dynamic Rankings (动态区间第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

poj2104 主席树 区间K大 在线 无修改

关于主席树: 主席树(Chairman Tree)是一种离线数据结构,使用函数式线段树维护每一时刻离散之后的数字出现的次数,由于各历史版本的线段树结构一致,可以相减得出区间信息,即该区间内出现的数字和对应的数量,由于在线段树内,左子树代表的数字都小与右子树,便可像平衡树一样进行K大询问.新建一颗树是\(O(logn)\),查询一次也为\(O(logn)\). 比划分树好想&写多了,但是在POJ上比划分树慢一些. CODE: 1 #include <cstdio> 2 #include

hdu 5919 主席树(区间不同数的个数 + 区间第k大)

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 849    Accepted Submission(s): 204 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?