主席树详解
来源:互联网 发布:广州女人街网络批发 编辑:程序博客网 时间:2024/05/29 07:42
主席树是一种线段树的变形,可以解决区间第k大的问题。下面我谈谈自己的理解,尽可能的讲清楚些。
假设现在有序列 a[5] = {1 , 4 , 5 , 3 , 2},有q个询问{l , r , k}问你[l , r]区间第k小的值是多少?
- 容易想到对被询问区间排个序,然后输出第k个数。这种方法最直观,但也是最费时的(时间复杂度爆炸),不可取。
- 另一种是先建立一个空树,再将[l , r]区间的值插入到树中,然后查找。
空树:
现在将[2 , 4]区间的值(4 , 5 , 3)插入到这颗树里.
插入后:
可以看到插入以后,[3,3],[4, 4] ,[5 5]的值变成了1代表[2 , 4]区间的数分布情况。有了这个树我们只需要遍历一遍就可以解决该区间第k大的问题了。但是这种方法有两个致命的缺陷!
- 每次查询都要重新建树,时间复杂度很高。
- 对每一次查询都要新建立一个树,太吃内存了,空间复杂度爆炸。
到了这里,只要解决了这两个问题,这个算法就是一个高效的算法了!我们注意到在插入的时候,每插入一个数,影响的只是这棵树上的一条路径上的个点受影响,利用这个性质,建树的时候可以只在前一个线段树的基础上增添log2n 个点就可以了,这样复杂度大大降低了。log2n
可以看到将3插入树中的时候,只影响了3个点。
我们可以建立n课树,对于树tree[i]插入的是[1,i]。这样在求区间[l,r]时,tree[r] - tree[l-1]就是我们要找的树,遍历这颗树就行了。自此主席树求静态区间第k大讲完,等再有空了补上带修改的区间第k大。
我的模板:
#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+10;struct A{ int x , idx; bool operator < (const A &rhs) const { return x < rhs.x; }};A a[maxn];struct tree{ int L , R , sum;}T[maxn*40];int n , m , cnt , ran[maxn] , root[maxn];void insert(int num , int &x , int l , int r){ T[cnt++] = T[x] , x = cnt - 1; T[x].sum += 1; if(l == r) return ; int mid = (l + r) / 2; if(num <= mid) insert(num , T[x].L , l , mid); else insert(num , T[x].R , mid+1 , r);}int query(int i , int j , int k , int l , int r){ if(l == r) return l; int t = T[T[j].L].sum - T[T[i].L].sum; int mid = (l + r) / 2; if(t >= k) return query(T[i].L , T[j].L , k , l , mid); return query(T[i].R , T[j].R , k-t , mid+1 , r);}int main(){ int t , i , j , k; T[0].L = T[0].R = T[0].sum = 0; root[0] = 0; scanf("%d", &t); while(t--) { scanf("%d %d", &n , &m); for(i=1; i<=n; i++) { scanf("%d", &a[i].x); a[i].idx = i; } sort(a+1 , a+n+1); for(i=1; i<=n; i++) ran[a[i].idx] = i; //主席树必须要离散化。 cnt = 1; for(i=1; i<=n; i++) { root[i] = root[i-1]; insert(ran[i] , root[i] , 1 , n); //建立n颗线段树 } while(m--) { scanf("%d %d %d", &i , &j , &k); printf("%d\n", a[query(root[i-1] , root[j] , k , 1 , n)].x); } } return 0;}
阅读全文
0 0
- 主席树详解
- 主席树详解
- 主席树详解
- poj 2104 主席树 详解
- 主席、树、主席树!
- 主席数详解
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- const 和 #define 的区别
- Unity编辑器拓展之二:ReorderableList可重新排序的列表框(复杂使用)
- R语言自定义函数及基本分支循环结构
- spark2.2.0源码学习过程记录:Day4
- hdu_2647_拓扑排序_邻接表或者vector_优化内存_拓扑+贪心_用的是拓扑思想_并不是拓扑
- 主席树详解
- 小程序数字精确度问题
- spark2.2.0源码学习过程记录:Day5
- PsSetCreateProcessNotifyRoutine妙用
- 利用Data URL(data:image/jpg;base64,)将小图片生成数据流形式
- Codeforces Round #431 (Div. 2) D Rooter's Song
- hdu 4965 Fast Matrix Calculation 矩阵
- 一个例子学会CountDownLatch
- 设计师到底能不能自己进行可用性测试(上)