poj 2104 K-th Number ———————— 主席树模板

题目链接:poj_2104 K-th Number


首先我们要知道Tree中所存储的东西,Tree.sum是它所代区间中有几个数,Tree.l 是它的左区间所在结点的下标,Tree.r 是它的右区间所在结点的下标。


感觉代码有几个神奇之处:

1. root[i] = root[i-1]; 直接把 [1,i-1] 这课线段树上存储的东西 给了 [1,i] 这颗线段树 ,
相当于第i颗线段树只需要特指 logn个点来更新被 第i个数改变的点,其他点由于没有更新,所以可以沿用第i-1 颗线段树上的内容。

2. Tree[0].l=Tree[0].r=Tree[0].sum=root[0]=0; 创建了第0颗线段树,和第0个结点,这样所有的没有存储内容的结点都可以用第0个结点所表示。

3. void update(int x,int &fre,int l,int r)
	Tree[++cnt] = Tree[fre];
	fre = cnt ;
	update(x,Tree[fre].l,l,m);
动态建点,给它分配下标,然后将下标带回 Tree[fre].l

 
 


代码:

#include<cstdio>
#include<algorithm>
#define maxn 100100
using namespace std;
struct nn{
	int value,id;
}num[maxn];
bool cmp(nn x,nn y){
	return x.value<y.value;
}
struct node{
	int l,r,sum;
}Tree[maxn*20];
int root[maxn];
int a[maxn],cnt;
void update(int x,int &fre,int l,int r){
	Tree[++cnt] = Tree[fre];
	fre = cnt ;
	Tree[fre].sum++;
	if (l==r) return ;
	int m = (l+r)>>1;
	if (x<=m){
		update(x,Tree[fre].l,l,m);
	}else{
		update(x,Tree[fre].r,m+1,r);
	}
}
int query(int a,int b,int k,int l,int r){
	
	if (l==r) return l;
	int num_sum = Tree[Tree[b].l].sum - Tree[Tree[a].l].sum;
	int m = (l+r)>>1;
	
//	printf("a=%d   b=%d   k=%d   l=%d   r=%d   num_sum=%d   m=%d  \n",a,b,k,l,r,num_sum,m);
	
	if (num_sum<k){
		return query(Tree[a].r,Tree[b].r,k-num_sum,m+1,r);
	}else{
		return query(Tree[a].l,Tree[b].l,k,l,m);
	}
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++){
		scanf("%d",&num[i].value);
		num[i].id = i;
	} 
	sort(num+1,num+1+n,cmp);
	for (int i=1;i<=n;i++){
		a[num[i].id] = i;
	}
	cnt=Tree[0].l=Tree[0].r=Tree[0].sum=root[0]=0; 
	
	for (int i=1;i<=n;i++){
		root[i] = root[i-1];
		update(a[i],root[i],1,n);
	}
	
//	for (int i=1;i<=n;i++){
//		printf("root[%d] = %d\n",i,root[i]);
//	}
	
//	for (int i=0;i<=cnt;i++){
//		printf("i = %d, Tree[].l=%d, Tree[].r=%d ,Tree[].sum=%d\n",i,Tree[i].l,Tree[i].r,Tree[i].sum);
//	}
	
	for (int i=1;i<=m;i++){
		int aa,bb,kk;
		scanf("%d%d%d",&aa,&bb,&kk);
		printf("%d\n",num[query(root[aa-1],root[bb],kk,1,n)].value);
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/leibniz_zhang/article/details/78198065