主席树初步

主席树是一个很神奇的东西,效率次于划分树。

关于思路,还是用图片来展示吧:


附上poj2104代码:

#include
#include
#include
#include
#include
#include
#include
#define M 100000+5
using namespace std;
/*
以poj2104求[l,r]第k大的数为例探究主席树 
*/
struct node
{
	int l,r,size;
	node(){l=r=size=0;
	}
}T[20*M];
int root[M];//记录第i个子树的根
int tot;//各点标号 
int m;
int a[M];//读入数组
int t[M];//离散数组 1,5,7,9等数字离散后 t[1]=1 t[2]=5 t[3]=7
int pos(int x)
{
	return lower_bound(t+1,t+m+1,x)-t;//寻找在离散数组中的位置 
	/*int l=1,r=m;
	while(l=k)return query(T[i].l,T[j].l,l,mid,k);
	else return query(T[i].r,T[j].r,mid+1,r,k-cha);
}
int main()
{
	while(scanf("%d%d",&n,&q)!=EOF)
	{
		for(int i=1;i<=n;i++)
    	{
		    scanf("%d",&a[i]);
	    	t[i]=a[i];
    	}
    	sort(t+1,t+n+1,cmp);
    	m=unique(t+1,t+n+1)-t-1;
    	m++;t[m]=0x3f3f3f3f; 
    	tot=0;
    	root[0]=build(1,m);//初始化树
    	for(int i=1;i<=n;i++)//每个点的建树通过Logn的上传修改 
	    {
		    int k=pos(a[i]);//k是a[i]这个数对应在离散后的数中的位置 
		    root[i]=updata(root[i-1],1,m,k,1);//传递修改 ,参数含义见上 
    	} 
	    //处理好之后剩下的是查询
	    for(int i=1;i<=q;i++)
    	{
	    	int l,r,k;//寻找[l,r]区间里的第k小的元素 
		    scanf("%d%d%d",&l,&r,&k);
	    	printf("%d\n",t[query(root[l-1],root[r],1,m,k)]);//查询[l,r]里面第k小的元素 
	    } 
	}
	return 0;
}


你可能感兴趣的:(数据结构,主席树,线段树)