HDOJ 2665 Kth number(归并树)

Kth number

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


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
 

和POJ2104一模一样,具体题解看这里: 题解  

代码如下:

#include
#include
#include 
#include
using namespace std;
#define maxn 100010
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
vectorT[maxn<<2];

void build(int l,int r,int i)//建立线段树,i是节点编号,与区间[l,r)相对应 
{
	if(l==r)
	{
		int val;
		scanf("%d",&val);
		T[i].clear();
		T[i].push_back(val);
		return ;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	T[i].resize(r-l+1);//调整容器T[i]的大小为 r-l+1 
	merge(T[i<<1].begin(),T[i<<1].end(),T[i<<1|1].begin(),T[i<<1|1].end(),T[i].begin() );
	//将两个儿子的数列合并 
}

//计算区间[ql,qr)中不超过val的个数 
int query(int ql,int qr,int val,int l,int r,int i)
{
	if(ql==l&&qr==r)
		return upper_bound(T[i].begin(),T[i].end(),val)-T[i].begin();
	int mid=(l+r)>>1;
	if(qr<=mid)
		return query(ql,qr,val,lson);
	else if(ql>mid)
		return query(ql,qr,val,rson);
	return query(ql,mid,val,lson)+query(mid+1,qr,val,rson);
}

int main()
{
	int n,m,a,b,k,c,left,right,mid,t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		build(1,n,1);
		while(m--)
		{
			scanf("%d%d%d",&a,&b,&k);
			left=-1; right=n-1;
			while(right-left>1)//二分查找 
			{
				mid=(left+right)>>1;
				c=query(a,b,T[1][mid],1,n,1);
				if(c>=k)
					right=mid;
				else
					left=mid;
			}
			printf("%d\n",T[1][right]);
		}
	}
	return 0;
}


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