区间第k大的数 划分树模板
来源:互联网 发布:淘宝积分兑换购物券 编辑:程序博客网 时间:2024/05/22 02:27
一个长度为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个数,对应序列中的元素。(0 <= Sii <= 10^9)
第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 50000)
第N + 3 - N + Q + 2行:每行3个数,对应查询的起始编号i和结束编号j,以及k。(0 <= i <= j <= N - 1,1 <= k <= j - i + 1)
Output
共Q行,对应每一个查询区间中第K大的数。
Sample Input
5
1
7
6
3
1
3
0 1 1
1 3 2
3 4 2
Sample Output
7
6
1
参考:http://blog.csdn.net/shiqi_614/article/details/8041390
代码:
#include<bits/stdc++.h>const int INF = 0x3f3f3f3f;const int Maxn = 100005;#define MST(s,q) memset(s,q,sizeof(s))#define Lchild id<<1#define Rchild (id<<1)+1using namespace std;int order[Maxn], tree[20][Maxn], toleft[20][Maxn];void build(int L, int R, int id) { if (L == R) return; int mid = (L + R) >> 1; int same = mid - L + 1, Ln = L, Rn = mid + 1; for (int i = L; i <= R; i++) if (tree[id][i] < order[mid]) same--; for (int i = L; i <= R; i++) { int flag = 0; if (tree[id][i] < order[mid] || (tree[id][i] == order[mid] && same > 0)) { flag = 1; tree[id + 1][Ln++] = tree[id][i]; if (tree[id][i] == order[mid])same--; } else { tree[id + 1][Rn++] = tree[id][i]; } toleft[id][i] = toleft[id][i - 1] + flag; } build(L, mid, id + 1); build(mid + 1, R, id + 1);}int query(int s, int e, int k, int L, int R, int id) { if (L == R) return tree[id][L]; int mid = (L + R) >> 1; int Lx = toleft[id][s - 1] - toleft[id][L - 1]; int Ly = toleft[id][e] - toleft[id][s - 1]; int Rx = s - 1 - L + 1 - Lx; int Ry = e - s + 1 - Ly; if (Ry >= k) return query(mid + 1 + Rx, mid + 1 + Rx + Ry - 1, k, mid + 1, R, id + 1); else return query(L + Lx, L + Lx + Ly - 1, k - Ry, L, mid, id + 1);//// if (Ly >= k) return query(L + Lx, L + Lx + Ly - 1, k, L, mid, id + 1);// else return query(mid + 1 + Rx, mid + 1 + Rx + Ry - 1, k - Ly, mid + 1, R, id + 1);}int main() { int N, M; while (cin >> N) { MST(tree, 0); MST(toleft, 0); for (int i = 1; i <= N; i++) scanf("%d", &tree[0][i]); for (int i = 1; i <= N; i++) order[i] = tree[0][i]; sort(order + 1, order + 1 + N); build(1, N, 0); cin >> M; int a, b, k; while (M--) { scanf("%d%d%d", &a, &b, &k); cout << query(a + 1, b + 1, k, 1, N, 0) << endl; } }}
0 0
- 区间第k大的数 划分树模板
- poj 2401 划分树 求区间第k大的数
- 区间第K大(划分树)
- 划分树的学习(求区间第k大的数字)&&分块求区间第k大
- POJ 2104-K-th Number(划分树)求区间内第k小的数
- 区间第k大的数(主席树)
- 划分树——求区间第k大值
- POJ 2104 区间第K大值(划分树做法)
- 静态区间第k大(划分树)
- poj查询区间第k大(划分树)
- 划分树(基本用法是求给定区间的第k大的值)
- POJ 2761-Feed the dogs(划分树)求区间内第k小的数
- 第k大的数(快速排序的划分过程)
- 查找给定区间内第K大/小的数
- 51Nod-1175-区间中第K大的数
- 51nod 1175 区间中第K大的数
- 主席树模板(区间第k大!)hdu2665
- 主席树查询区间第K大模板
- Android Studio 常用快捷键整理
- 无法插入中文修改mysql表的编码格式
- zookeeper中启动出现闪退
- tomcat启动报错
- java基础学习(11)字符串
- 区间第k大的数 划分树模板
- JavaScript学习笔记36-操作form
- linux解压命令
- 【数据结构-栈】杂记
- bzoj4822 cqoi2017 老C的任务【树状数组+扫描】
- 浪潮之巅——信息时代下的商业社会随想
- 排序练习1:HDOJ 2561 几种简单排序
- javaSE学习16_面向对象
- HDU 3671 Boonie and Clyde (tarjan+割点变形)