Kth number (HDU_2665) 划分树

Kth number

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7845    Accepted Submission(s): 2440


Problem Description
Give you a sequence and ask you the kth big number of a inteval.
 

Input
The first line is the number of the test cases. 
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere. 
The second line contains n integers, describe the sequence. 
Each of following m lines contains three integers s, t, k. 
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
 

Output
For each test case, output m lines. Each line contains the kth big number.
 

Sample Input
   
   
   
   
1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2
 

Sample Output
   
   
   
   
2
题目大意:求kth值.
解题思路:参考POJ_2104,99%相同。
代码如下:
#include"cstdio"
#include"iostream"
#include"algorithm"
#define MAXN 100000 + 10
using namespace std;
struct seq{
	int order;
	int value;
}a[MAXN];
struct node{	//划分树 
	int val[MAXN];	//存值 
	int left[MAXN];	//划入左子树的个数 
	int deep;		//深度 
}tree[25];
bool cmp(seq a,seq b){
	return a.value<b.value;
} 
//构建划分树 
void Build(int d,int l,int r){
	if(l==r) return ;
	int mid=(l+r)>>1;
	int p=0,t=0;
	for(int i=l;i<=r;i++){
		if(tree[d].val[i]<=mid){//划入左子树 
			tree[d+1].val[l+p]=tree[d].val[i];
			p++;
			tree[d].left[i]=p; 
		}else{//划入右子树 
			tree[d+1].val[mid+1+t]=tree[d].val[i];
			t++;
			tree[d].left[i]=p; //是p不是t 
		}
	}
	Build(d+1,l,mid);
	Build(d+1,mid+1,r);
}
//在大区间(l,r)中查找小区间(ll,rr)的第k大值 	
int Query(int d,int l,int r,int ll,int rr,int k){ 
	if(ll==rr) return (tree[d].val[ll]);
	int ls=0,rs=0;	//ls,rs用于确定小区间
	if(ll>l)
		ls=tree[d].left[ll-1];
		else ls=0;
	int mid=(l+r)>>1;
	rs=tree[d].left[rr];
	if(rs-ls>=k) 
		return Query(d+1,l,mid,l+ls,l+rs-1,k);
	else 
		return Query(d+1,mid+1,r,(mid+1)+(ll-l-ls),(mid+1)+rr-l-rs,k-(rs-ls)); 
	if(ll==rr) return tree[d].val[ll];	
}
int main(){
	int n,m;
	int i;
	int T;
	scanf("%d",&T); 
	while(T--){
		scanf("%d%d",&n,&m); 
		//存值并进行离散化 
		for(i=1;i<=n;i++){
			scanf("%d",&a[i].value);
			a[i].order=i;
		}
		sort(a+1,a+1+n,cmp);
		for(i=1;i<=n;i++){
			tree[0].val[a[i].order]=i;
		}
		Build(0,1,n);
		while(m--){
			int ll,rr,k;
			scanf("%d%d%d",&ll,&rr,&k);
			printf("%d\n",a[Query(0,1,n,ll,rr,k)].value);
		}
	}
	return 0;
}


你可能感兴趣的:(线段树,划分树)