划分树 poj2104 hdu5249

Posted lcchuguo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了划分树 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(0x10技术分享9技术分享)技术分享的请求被推进管道。


  "out": 代表服务拉取了管道头部的请求。
  "query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,假设当前管道内有m条请求, 我想知道。升序排序后第floor(m/2)+1技术分享th技术分享技术分享 条请求的重要值.

为了让题目简单,全部的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 109 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的主要内容,如果未能解决你的问题,请参考以下文章

poj 2104 (划分树模板)

HDU 2665 && POJ 2104(主席树)

K-th Number POJ - 2104 划分树

poj2104 K-th Number(划分树)

poj 2104 K-th Number (划分树)

[划分树] POJ 2104 K-th Number