[POJ 2104]K-th Number

danihao123 posted @ 2016年2月11日 10:42 in 题解 with tags POJ 区间K大 主席树 , 603 阅读
转载请注明出处:http://danihao123.is-programmer.com/

我擦终于A了这题了!

主席树坑点多……

最好不要写指针主席树,不然容易TLE……(自带常数?

并且注意,一定要把数组开大,开大,再开大,重要的事情说三遍

代码:

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100001,maxnode=maxn*20;
int sumv[maxnode];
int lc[maxnode];
int rc[maxnode];
int root[maxn];
int A[maxn];
int A2[maxn];
int size,tot=0;
int build_tree(int L,int R){
	++tot;
	if(L==R)
		return tot;
	int ans=tot,M=L+(R-L)/2;
	lc[ans]=build_tree(L,M);
	rc[ans]=build_tree(M+1,R);
	return ans;
}
int p;
int update(int o,int L,int R){
	int roo=++tot;
	sumv[roo]=sumv[o];
	lc[roo]=lc[o];
	rc[roo]=rc[o];
	if(R>L){
		int M=L+(R-L)/2;
		if(p<=M)
			lc[roo]=update(lc[tot],L,M);
		else
			rc[roo]=update(rc[tot],M+1,R);
	}
	sumv[roo]++;
	return roo;
}
int query(int lo,int ro,int L,int R,int k){
	if(L==R)
		return L;
	int M=L+(R-L)/2,lc_siz=sumv[lc[ro]]-sumv[lc[lo]];
	if(k<=lc_siz)
		return query(lc[lo],lc[ro],L,M,k);
	else
		return query(rc[lo],rc[ro],M+1,R,k-lc_siz);
}
void init_tree(int n){
	register int i;
	sort(A2,A2+n);
	size=unique(A2,A2+n)-A2;
	root[0]=build_tree(1,size);
	for(i=1;i<=n;i++){
		p=lower_bound(A2,A2+size,A[i-1])-A2+1;
		root[i]=update(root[i-1],1,size);
	}
}
int main(){
	int n,m,u,v,k;
	register int i;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++){
		scanf("%d",&A[i]);
		A2[i]=A[i];
	}
	init_tree(n);
	for(i=0;i<m;i++){
		scanf("%d%d%d",&u,&v,&k);
		printf("%d\n",A2[query(root[u-1],root[v],1,size,k)-1]);
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter