劃分樹

Enjoy_process發表於2018-09-11

模板

#include<iostream>
#include<algorithm>
 
using namespace std;
const int N=100100;
const int Deep=20;
 
struct PartitionTree{
	int num[N],cnt[N];
}tree[Deep];
 
int sorted[N];
 
void build(int deep,int l,int r)
{
	if(l==r)
	  return;
	int mid=(l+r)>>1;
	int key=sorted[mid];
	int scnt=mid-l+1;
	for(int i=l;i<=r;i++)
	  if(tree[deep].num[i]<key)
	    scnt--;
	int p=l-1,p2=mid;
	for(int i=l,cnt=0;i<=r;i++){
		int num=tree[deep].num[i];
		if(num<key||(num==key&&scnt)){
			if(num==key)
			  scnt--;
			cnt++;
			tree[deep+1].num[++p]=num;
		}
		else
		  tree[deep+1].num[++p2]=num;
		tree[deep].cnt[i]=cnt;
	}
	build(deep+1,l,mid);
	build(deep+1,mid+1,r);
}
 
int query(int deep,int l,int r,int L,int R,int k)
{
	if(l==r)
	  return tree[deep].num[l];
	int mid=(l+r)>>1;
	int left=0,sum_in_left=tree[deep].cnt[R];
	if(l!=L){
		left=tree[deep].cnt[L-1];
		sum_in_left-=left;
	}
	if(sum_in_left>=k){
		L=l+left;
		R=L+sum_in_left-1;
		return query(deep+1,l,mid,L,R,k);
	}
	else{
		int a=L-l-left;
		int b=R-L+1-sum_in_left;
		L=mid+1+a;
		R=L+b-1;
		return query(deep+1,mid+1,r,L,R,k-sum_in_left);
	}
}
 
int main()
{
	int n,m,L,R,k;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&sorted[i]);
		tree[0].num[i]=sorted[i];
	}
	sort(sorted+1,sorted+1+n);
	build(0,1,n);
	while(m--){
		scanf("%d%d%d",&L,&R,&k);
		printf("%d\n",query(0,1,n,L,R,k));
	}
	return 0;
}

問題集錦

POJ2104 K-th Number【劃分樹】

相關文章