hdu2665 (划分树_查询区间第k大)

测板子的题目。划分树理解起来很容易,和线段树差不多,注意查询函数的下标很容易写错。

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
using namespace std;
#define maxn 100005
int t[20][maxn],sum[20][maxn];
int a[maxn];
int n;
void build(int p,int l,int r)
{
	int lm=0;int mid=(l+r)/2;
	int ls=l,rs=mid+1;
	for(int i=mid;i>=l;i--)
	{
		if(a[i]==a[mid]) lm++;
		else break;
	}
	for(int i=l;i<=r;i++)
	{
		if(i==l) sum[p][i]=0;
		else sum[p][i]=sum[p][i-1];
		if(t[p][i]==a[mid])
		{
			if(lm)
			{
				lm--;sum[p][i]++;t[p+1][ls++]=a[mid];
			}
			else
			t[p+1][rs++]=a[mid];
		}
		else if(t[p][i]<a[mid])
		{
			sum[p][i]++;
			t[p+1][ls++]=t[p][i];
		}
		else
		{
			t[p+1][rs++]=t[p][i];
		}
	}
	if(l==r) return ;
	build(p+1,l,mid);
	build(p+1,mid+1,r);
}
int query(int p,int l,int r,int ql,int qr,int k)
{
	if(l==r) return t[p][l];
	int s,ss,mid=(l+r)/2;
	if(ql==l) s=0,ss=sum[p][qr];
	else s=sum[p][ql-1],ss=sum[p][qr]-s;
	if(k<=ss)
	return query(p+1,l,mid,l+s,-1+l+sum[p][qr],k);
	else return query(p+1,mid+1,r,mid+1+ql-l-s,mid+1+qr-l-sum[p][qr],k-ss);
}
int main()
{
	int q;cin>>q;
	while(q--)
	{
		int T;
		cin>>n>>T;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			t[0][i]=a[i];
		}
		sort(a+1,a+n+1);
		build(0,1,n);
		while(T--)
		{
			int l,r,k;cin>>l>>r>>k;
			cout<<query(0,1,n,l,r,k)<<endl; 
		}		
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37632935/article/details/80622835
今日推荐