K-th Number POJ - 2104 (主席树模板)

版权声明: https://blog.csdn.net/nucleare/article/details/88969748

K-th Number

 POJ - 2104 

问题描述

给定一个数组 a[1...n],数组元素各不相同,你的程序要对每次查询Q(i,j,k)作出回答,其中Q(i,j,k)的含义为在数组a[i...j]中第k大的数字.
例如,给出数组a=(1, 5, 2, 6, 3, 7, 4).查询语句为Q(2, 5, 3),即从(5,2,6,3)中找出第3大的元素,将之排序得到(2, 3, 5, 6),故第三大的数字是5,所以这次查询的结果应当为5.

输入格式

数据第1行有两个数字N与M,分别表示数组元素的个数与查询次数(1 <= n <= 100000, 1 <= m <= 5000).
第2行有N个数字,表示数组中的各元素,数组中各元素互不相同,并且每个数字的绝对值不超过109. 
接下来的m行,每行包含3个数字i,j,k,(1 <= i <= j <= n, 1 <= k <= j - i + 1),表示一次查询Q(i,j,k)

输出格式

对于每次查询,输出查询结果,即a[i...j]中第k大的数字,每个结果占一行

Sample Input

7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3

Sample Output

5
6
3

Hint

输入数据较多,请使用C语言风格的输入输出语句(scanf(),printf()),否则可能发生Time Limit Exceed.

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
const int N = 1e5 + 7;
const int M = 4e6 + 7; //太大爆 
int root[N], tot; //根,总数 
struct Tree {
	int l, r, sum;
} tree[M];  
vector<int> v; //离散化 
int a[N]; //原数组 
int getid(int x) { //hash
	return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; 
} 
void update(int l, int r, int L, int &R, int pos) {
	tree[++tot] = tree[L], tree[tot].sum++, R = tot;
	if (l == r) return;
	int mid = (l + r) / 2;
	if (pos <= mid) update(l, mid, tree[L].l, tree[R].l, pos); //只更新一条链 
	else update(mid+1, r, tree[L].r, tree[R].r, pos);
}
int query(int l, int r, int L, int R, int k) {
	if (l == r) return l;
	int mid = (l + r) / 2;
	int sum = tree[tree[R].l].sum - tree[tree[L].l].sum;
	if (sum >= k) return query(l, mid, tree[L].l, tree[R].l, k);
	else return query(mid+1, r, tree[L].r, tree[R].r, k-sum);
}
int main() {
	int n, q;
	while (~scanf ("%d %d", &n, &q)) {
		for (int i = 1; i <= n; ++i) scanf ("%d", &a[i]), v.push_back(a[i]);
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()), v.end()); //去重 
		for (int i = 1; i <= n; ++i) {
			update(1, n, root[i-1], root[i], getid(a[i]));  
		}
		int l, r, k; //求[l, r]排序后的第k个数 
		while (q--) {
			scanf ("%d %d %d", &l, &r, &k);
			printf ("%d\n", v[query(1, n, root[l-1], root[r], k)-1]);
		} 
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/nucleare/article/details/88969748