划分树 poj2104 hdu5249

KPI

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 616    Accepted Submission(s): 261


Problem Description
你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度。数十亿的请求被推到一个大管道后同时服务从管头拉取请求。让我们来定义每个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。现在给你服务记录,有时我想知道当前管道内请求的重要值得中间值。
 

Input
有大约100组数据。

每组数据第一行有一个 n(1n10000) ,代表服务记录数。

接下来有n行,每一行有3种形式
  "in x": 代表重要值为 x(0x109) 的请求被推进管道。
  "out": 代表服务拉取了管道头部的请求。
  "query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,如果当前管道内有m条请求, 我想知道,升序排序后第 floor(m/2)+1th 条请求的重要值.

为了让题目简单,所有的x都不同,并且如果管道内没有值,就不会有"out"和"query"操作。
 

Output
对于每组数据,先输出一行

Case #i:
然后每一次"query",输出当前管道内重要值的中间值。
 

Sample Input
   
   
   
   
6 in 874 query out in 24622 in 12194 query
 

Sample Output
   
   
   
   
Case #1: 874 24622
 
K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 41138   Accepted: 13447
Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
The second line contains n different integer numbers not exceeding 10 9 by their absolute values --- the array for which the answers should be given. 
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

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

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

这两题都 要求子区间的第k大数,如果用快排之后,再查,复杂度太大,不能过,就要用到划分树了,划分树,其实,就是线段树的

一个变种了,当然,这样做查询是lg(n)级别,建树是n * lg(n),再加上一次快排,也是n * lg(n),差不多就可以过了!

先来看看划分树,我们在线段树的基础上,如果每个结点都保存了,当前子段向左子树走的个数,如果,查询的k要小于,查询段向左走的个数,自然,我们向左子树就可以查到结果,如果,k>向左走的个数,当然要向右找k-midcount个数,区间的变换,我们可以

推一下向左走就是l + scount, l + ecount - 1,向右走就是mid + 1 + s - l - scount, mid + 1 + e - l - ecount,其中scount就是s之前向左走的个数, ecount,就是e之前向左走的个数。

上核心代码

#define MID(a,b) (((a)+(b))>>1)
#define N 100050
int num[20][N], val[20][N];
//第i层,向左包括自已,向左子树的个数,当前的值
int pri[N], sorted[N];
//原始和排序后的数列
char str[20];
void build(int l, int r, int layer){
	if (l >= r){
		return;
	}
	int mid = MID(l, r);
	int ql = l, qr = mid + 1, leftCount = mid, eqCount = 0;
	for (int i = l; i <= r; i++)
		leftCount -= val[layer][i] < sorted[mid];
	for (int i = l; i <= r; i++){
		if (i == l){
			num[layer][i] = 0;
		}
		else{
			num[layer][i] = num[layer][i - 1];
		}
		if (val[layer][i] < sorted[mid]){
			num[layer][i]++;
			val[layer + 1][ql++] = val[layer][i];
		}
		else if (val[layer][i] > sorted[mid]){
			val[layer + 1][qr++] = val[layer][i];
		}
		else {
			if (eqCount < leftCount){
				eqCount++;
				num[layer][i]++;
				val[layer + 1][ql++] = val[layer][i];
			}
			else {
				val[layer + 1][qr++] = val[layer][i];
			}
		}
	}
	build(l, mid, layer + 1);
	build(mid + 1, r, layer + 1);
}
//在layer层l到r间,找s-e之间的第k大数
int query(int l, int r, int layer, int s, int e, int k){
	if (l >= r || s >= e){
		return val[layer][s];
	}
	int scount, ecount, mid = MID(l, r);
	if (s == l){
		scount = 0, ecount = num[layer][e];
	}
	else {
		scount = num[layer][s - 1], ecount = num[layer][e];
	}
	int midcount = ecount - scount;
	if (k <= midcount){
		return query(l, mid, layer + 1, l + scount, l + ecount - 1, k);
	}
	else {
		return query(mid + 1, r, layer + 1, mid + 1 + s - l - scount, mid + 1 + e - l - ecount, k - midcount);
	}
}
int main()
{
	int tcase, tcasenum = 0;
	int n, k, q, s, e, begin = 1, nn, qcount, m;
	while (S2(n, m) != EOF)
	{
		FI(n){
			S(val[0][i+1]);
		}
		FI(n){
			sorted[i + 1] = val[0][i + 1];
		}
		sort(sorted + 1, sorted + n + 1);
		build(1, n, 0);
		FI(m){
			S2(s, e); S(q);
			Prn(query(1, n, 0, s,e,q));
		}
	}
	return 0;
}


你可能感兴趣的:(划分树 poj2104 hdu5249)