HDU2665--Kth Number(划分树)
来源:互联网 发布:qq点亮图标软件 编辑:程序博客网 时间:2024/06/04 19:48
题目大意:给出一个数列,求区间第K小数
分析:划分树。就是基于快排原理的线段树。线段树的每一层都类似于一次快排的结果。
建树时,把小于as[mid]的数分到左边,大于as[mid]的数分到右边,相等的根据情况分到左右两边。同时,用一个sum[d][i]数组记录第d层前i个元素比as[mid]小的个数,以便于之后的查询操作时缩小区间以及k。
查询,代码注释蛮清楚的了。[L, R]表示要查询的区间。
int Query(int d, int l, int r, int L, int R, int k) { int s, ss; //s表示区间[l, L)有多少个元素比as[mid]小,ss表示区间[L, R]有多少个元素比as[mid]小 int mid = (l+r)>>1; if(l == r) return tree[d][l]; if(l == L) s = 0; //特判。因为区间是左闭右开的 else s = sum[d][L-1]; ss = sum[d][R]-s; if(ss >= k) return Query(d+1, l, mid, l+s, l+s+ss-1, k); else return Query(d+1, mid+1, r, mid+1+L-l-s, mid+1+R-l-s-ss, k-ss); //L-l-s表示这次Query的区间之前有多少个大于as[mid]的数分到了右边} //R-l-s-ss表示这次Query的区间以及它之前共有多少个大于as[mid]的数分到了右边
代码:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 111111;int tree[20][maxn]; //每一层类似于一次快排的结果int sum[20][maxn]; //sum[d][i]表示第d层前i个元素有多少个比as[mid]小,加上等于as[mid]的元素分到左区间的个数int a[maxn], as[maxn]; //a数组表示原始数组,as数组表示排序后数组void Build(int d, int l, int r) { int mid = (l+r)>>1; int lpos = l, rpos = mid+1; //lpos记录放入下一层的左区间的位置,rpos则是记录右区间 int lsame = mid-l+1; //lsame记录有前半个区间有多少个数与as[mid]相等,初始时假设全都相等 for(int i = l; i <= mid; i++) if(as[i] < as[mid]) lsame--; for(int i = l; i <= r; i++) { if(i == l) sum[d][i] = 0; else sum[d][i] = sum[d][i-1]; if(tree[d][i] == as[mid]) { if(lsame) { //lsame>0说明与as[mid]相同的元素还可以分到左区间 lsame--; sum[d][i]++; tree[d+1][lpos++] = tree[d][i]; } else tree[d+1][rpos++] = tree[d][i]; } else if(tree[d][i] < as[mid]) { sum[d][i]++; tree[d+1][lpos++] = tree[d][i]; } else tree[d+1][rpos++] = tree[d][i]; } if(l != r) { Build(d+1, l, mid); Build(d+1, mid+1, r); }}int Query(int d, int l, int r, int L, int R, int k) { int s, ss; //s表示区间[l, L)有多少个元素比as[mid]小,ss表示区间[L, R]有多少个元素比as[mid]小 int mid = (l+r)>>1; if(l == r) return tree[d][l]; if(l == L) s = 0; //特判。因为区间是左闭右开的 else s = sum[d][L-1]; ss = sum[d][R]-s; if(ss >= k) return Query(d+1, l, mid, l+s, l+s+ss-1, k); else return Query(d+1, mid+1, r, mid+1+L-l-s, mid+1+R-l-s-ss, k-ss); //L-l-s表示这次Query的区间之前有多少个大于as[mid]的数分到了右边} //R-l-s-ss表示这次Query的区间以及它之前共有多少个大于as[mid]的数分到了右边int main() { int T, n, m; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); tree[0][i] = as[i] = a[i]; } sort(as+1, as+n+1); Build(0, 1, n); while(m--) { int L, R, k; scanf("%d%d%d", &L, &R, &k); printf("%d\n", Query(0, 1, n, L, R, k)); } } return 0;}
0 0
- HDU2665--Kth Number(划分树)
- HDU2665 Kth number(划分树模板题)
- hdu2665 Kth number(主席树模板)
- (主席树)hdu2665 Kth number
- HDU2665 Kth number 【归并树】
- 主席树 hdu2665 Kth number
- Kth number(划分树)
- hdu2665(划分树)
- HDU2665 Kth number(主席树入门)
- HDU2665 kth number 线段树做法
- HDU2665-主席树&模板-Kth number
- POJ2104 hdu2665 主席树入门 Kth-number
- hdu2665-Kth number
- HDU2665-Kth number
- HDU2665 Kth number
- 划分树 Kth number
- hdu 2665 Kth number(划分树)
- HDU 2665 Kth number(划分树)
- QT显示图片
- GPS跟踪器
- 一个有Bug的绘图软件
- html,列表<ol>,<ul>,<dl>
- 浅谈HTTP中Get与Post的区别
- HDU2665--Kth Number(划分树)
- leetCode4.1.1(Valid Parentheses)
- UI中常用的4种传值
- Spring Internals -- 目录
- 将UIView加载成WevView(不懂的可以留言)
- 利用Cookie实现用户浏览商品记录
- URL的格式
- 8.31学习总结
- php wsdl生成类