静态区间第k大(划分树)
来源:互联网 发布:php网店源码 编辑:程序博客网 时间:2024/05/18 01:52
POJ 2104为例【经典划分树问题】
思想:
利用快速排序思想,
- 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半。
- 查询时,在建树过程中利用
leftsum[p][i] 数组保存有多少个数划分到第p 层,第i 个位置的左边。每次查询计算出每个区间有多少数被放入左子树,小于等于k 则说明所求数在左子树,继续查询其左子树,反之则查询右子树。l==r 时则找到。 - 时间复杂度
O(nlogn+mlogn)
代码:
#include<cstdio>#include<algorithm>using namespace std;//[]const int maxn = 100010;int tree[20][maxn];//每层每个位置的值int sorted[maxn];//排好序的数组,方便寻找中值int leftsum[20][maxn];//有多少个数分到该层该位置左边void build(int p, int l, int r){ if(l == r) return; int mid = (l + r)/2; int same = mid - l + 1; int x = sorted[mid]; for(int i = l; i <= r; i++){ if(tree[p][i] < x) same--; }//与中值相等的数填满区间一半 int tl = l, tr = mid + 1; for(int i = l; i <= r; i++){ if(tree[p][i] < x) tree[p + 1][tl++] = tree[p][i]; else if(tree[p][i] == x && same>0){ tree[p + 1][tl++] = tree[p][i]; same--; }else tree[p + 1][tr++] = tree[p][i]; leftsum[p][i] = leftsum[p][l-1] + tl - l; } build(p + 1, l, mid); build(p + 1, mid + 1, r);}//[L,R]中的[l,r]的第k大数int query(int L, int R, int l, int r, int p, int k){ if(l == r) return tree[p][l]; int mid = (L + R)/2; int cnt = leftsum[p][r] - leftsum[p][l-1]; if(cnt >= k){ int newl = L + leftsum[p][l-1] - leftsum[p][L-1]; int newr = newl + cnt - 1; return query(L, mid, newl, newr, p+1, k); }else { int newr = r + leftsum[p][R] - leftsum[p][r]; int newl = newr - (r - l - cnt); return query(mid+1, R, newl, newr, p+1, k - cnt); }}int main (void){ int n, m;scanf("%d%d",&n,&m); for(int i = 1; i <=n; i++){//下标从1开始 scanf("%d",&tree[0][i]); sorted[i] = tree[0][i]; } sort(sorted+1, sorted+n+1); build(0, 1,n); int s, t, k; while(m--){ scanf("%d%d%d",&s,&t,&k); printf("%d\n",query(1, n, s, t, 0, k)); } return 0;}
划分树还是挺好理解的,接下来看看归并树和主席树。
0 0
- 静态区间第k大(划分树)
- 区间第K大(划分树)
- poj查询区间第k大(划分树)
- 划分树的学习(求区间第k大的数字)&&分块求区间第k大
- poj2761&&poj2104 主席树(静态区间第K大)
- 静态区间第k大(归并树)
- 静态区间第k大(主席树)
- 主席树(静态区间第k大)
- 静态区间第K大
- 划分树——求区间第k大值
- POJ 2104 区间第K大值(划分树做法)
- 区间第k大的数 划分树模板
- poj2140 K-th Number(静态区间第 k 大)
- 划分树(基本用法是求给定区间的第k大的值)
- 主席树求静态区间第K大
- 静态区间第k大(分桶法和平方分割)
- poj2761(静态区间第k大,treap)
- poj 2104 划分树(查询区间第k大数)
- android:Activity四种启动模式简介
- PAT_乙级1005
- php-fpm添加service服务
- [MyBatis日记](3)映射器配置文件与映射器接口
- 数据库知识自我检测(题目)
- 静态区间第k大(划分树)
- Windows多线程探究
- MyBatis日记
- 灭屏状态下,如何实现按某个键可点亮屏幕
- 约瑟夫问题的单向循环链表的代码实现
- 文件系统与NoSQL分布式存储技术对比
- 数据库自我检测(答案)
- BestCoder Round #72 (div.2) A.Clarke and chemistry
- 妈妈60大寿