Kth number HDU - 2665 (主席树)(模板)

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

求区间第k小

#include
#include
#include
#include
using namespace std;
const int maxn=100106;
int a[maxn];
int id[maxn];
int root[maxn];
int tot;
int n,m;


struct sgt{
	int lc,rc;
	int dat;
}t[maxn*21];

int build(int l,int r){
	int p=++tot;
	t[p].dat=0;
	if(l==r){
		t[p].dat=0;
		return p;
	}
	int mid=(l+r)/2;
	t[p].lc=build(l,mid);
	t[p].rc=build(mid+1,r);
	return p; 
}

int insert(int now,int l,int r,int x){
	int p=++tot;
	t[p]=t[now];
	t[p].dat++;	
	if(l==r)  return p;
	int mid=(l+r)/2;
	if(x<=mid) t[p].lc=insert(t[now].lc,l,mid,x);
	else t[p].rc=insert(t[now].rc,mid+1,r,x);
	return p;
}

int query(int pl,int pr,int l,int r,int k){
	if(l==r) return l;
	int mid=(l+r)/2;
	if(t[t[pr].lc].dat-t[t[pl].lc].dat>=k) return query(t[pl].lc,t[pr].lc,l,mid,k);
	else return query(t[pl].rc,t[pr].rc,mid+1,r,k-(t[t[pr].lc].dat-t[t[pl].lc].dat));
}





int main(){
	int ca;
	scanf("%d",&ca);
	while(ca--){
		tot=0;	
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			id[i]=a[i];
		}
		sort(id+1,id+1+n);
		int len=unique(id+1,id+1+n)-(id+1); 
		root[0]=build(1,len);
		for(int i=1;i<=n;i++){
			int p=lower_bound(id+1,id+1+len,a[i])-id;
			root[i]=insert(root[i-1],1,len,p);
		}
		for(int i=1;i<=m;i++){
			int tl,tr,k;
			scanf("%d%d%d",&tl,&tr,&k);
			printf("%d\n",id[query(root[tl-1],root[tr],1,len,k)]);
		}
	}
	return 0;
} 

你可能感兴趣的:(主席树,模板)