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

关于主席树:

主席树(Chairman Tree)是一种离线数据结构,使用函数式线段树维护每一时刻离散之后的数字出现的次数,由于各历史版本的线段树结构一致,可以相减得出区间信息,即该区间内出现的数字和对应的数量,由于在线段树内,左子树代表的数字都小与右子树,便可像平衡树一样进行K大询问。新建一颗树是\(O(logn)\),查询一次也为\(O(logn)\)。

比划分树好想&写多了,但是在POJ上比划分树慢一些。

CODE:

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxn = 100000 + 100;
 5
 6 int id[maxn], root[maxn], a[maxn], b[maxn], n, m, size;
 7 struct chairman_tree_node {
 8     int ls, rs, w;
 9 } T[maxn * 23];
10 void insert(int l, int r, int &pos, int val) {
11     T[++size] = T[pos], pos = size;
12     ++T[pos].w;
13     if(l == r) return ;
14     int mid = (l + r) >> 1;
15     if(val <= mid) insert(l, mid, T[pos].ls, val);
16     else insert(mid + 1, r, T[pos].rs, val);
17 }
18 int query(int p, int q, int l, int r, int k) {
19     if(l == r) return l;
20     int t = T[T[q].ls].w - T[T[p].ls].w;
21     int mid = (l + r) >> 1;
22     if(k <= t) return query(T[p].ls, T[q].ls, l, mid, k);
23     else return query(T[p].rs, T[q].rs, mid + 1, r, k - t);
24 }
25 bool cmp(int x, int y) {
26     return a[x] < a[y];
27 }
28 int main() {
29     scanf("%d%d", &n, &m);
30     for(int i = 1; i <= n; ++i) {
31         scanf("%d", &a[i]);
32         id[i] = i;
33     }
34     sort(id + 1, id + n + 1, cmp);
35     for(int i = 1; i <= n; ++i) {
36         b[id[i]] = i;
37     }
38     for(int i = 1; i <= n; ++i) {
39         root[i] = root[i - 1];
40         insert(1, n, root[i], b[i]);
41     }
42     for(int i = 1; i <= m; ++i) {
43         int l, r, k;
44         scanf("%d%d%d", &l, &r, &k);
45         printf("%d\n", a[id[query(root[l - 1], root[r], 1, n, k)]]);
46     }
47     return 0;
48 }

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

时间: 2024-12-14 18:05:13

poj2104 主席树 区间K大 在线 无修改的相关文章

poj2104 划分树 区间K大 在线 无修改

博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O(nlog^3n)\)),也可用划分树(\(O(nlogn + mlogn)\)).果断划分树...(以后再来看归并树...再来看...来看..看..) 划分树是个什么东西呢?为什么可以做区间k大呢? 想想平衡树做k大时是如何搞的,其实内在原理是一样的. 划分树分两个步骤:建树与询问,这两个步骤相互关

FZU 2237 中位数 主席树 树上k大

#include <cstdio> #include <cstring> #include <queue> #include <set> #include <stack> #include <cstdlib> #include <algorithm> #include <time.h> #include <vector> #include <cmath> using namespace

【区间k大】HDU 54512 CRB and Queries

通道 题意:区间k大,单点修改 思路:裸,复杂度n(lgn)^2 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int N = 60010 * 5; const int M = 100100 * 4; #define INF 1000000

BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池..尼玛终于过了..附zju2112代码于后. bzoj倒是过了,1A的感觉还是很爽的..可是时间不好看..这就是所谓\(O(nlog^3n)\)的复杂度的可怜之处么? 写挂的地方: insert一定要是传地址指针进去. delete时先把地址指针delete掉,最后把是地址指针指向左儿子or右儿子

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,?

poj2104(主席树)

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 35704   Accepted: 11396 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key inse

主席树区间第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&qu

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

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

POJ 2104:K-th Number(主席树静态区间k大)

题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var t:array[0..100000*50]of point; a,b,id,root:array[0..100000]of longint; n,i,m,x,y,k,v,len:longint; procedure qsort(l,h:longint); var i,j,t,m:longint; b