spoj Count on a tree【主席树】

题意:给一棵树还有一些询问求从u-v这条路径上点的权值的第K大。

我们可以从根开始维护主席树,就相当于以根为起点维护前缀和,这样我们可以求出u-v这条路径上对应点的权值,对u,v求一下lca(最近公共祖先),然后点的权值就是c[u]+c[v]-2*[lca(u,v)],然后同样二分找第k大。

#include
#include
#include
#include
using namespace std;
const int MAXN=100010;
struct EDGE
{
	int v,next;
}edge[MAXN<<1];
int dep[MAXN<<1],rank[MAXN],num,set[MAXN<<1];
bool vis[MAXN];
int head[MAXN],size;
int Min(int x,int y)
{
	return dep[x]r)
      swap(l,r);
    int x=RMQ(l,r);
    return set[x];
}
int lson[MAXN*40],rson[MAXN*40],c[MAXN*40];
int tot,n,m;
int T[MAXN];
int vec[MAXN],idx;
int build(int l,int r)
{
	int root=tot++;
	c[root]=0;
	if(l!=r)
	{
		int mid=(l+r)>>1;
		lson[root]=build(l,mid);
		rson[root]=build(mid+1,r);
	}
	return root;
}
int update(int root,int pos,int val)
{
	int newroot=tot++;
	int tmp=newroot;
	c[newroot]=c[root]+val;
	int l=1,r=idx;
	while(l>1;
		if(pos<=mid)
		{
			lson[newroot]=tot++;
			rson[newroot]=rson[root];
			newroot=lson[newroot];
			root=lson[root];
			r=mid;
		}
		else
		{
			rson[newroot]=tot++;
			lson[newroot]=lson[root];
			newroot=rson[newroot];
			root=rson[root];
			l=mid+1;
		}
		c[newroot]=c[root]+val;
	}
    return tmp;
}
int query2(int l_root,int r_root,int fa_root,int pos,int k)
{
	int l=1,r=idx;
	while(l>1;
		int tmp=c[lson[l_root]]+c[lson[r_root]]-2*c[lson[fa_root]]+(pos>=l&&pos<=mid);
		if(k<=tmp)
		{
			l_root=lson[l_root];
			r_root=lson[r_root];
			fa_root=lson[fa_root];
			r=mid;
		}
		else
		{
			k-=tmp;
			l_root=rson[l_root];
			r_root=rson[r_root];
			fa_root=rson[fa_root];
			l=mid+1;
		}
	}
	return l;
}
int HASH(int val)
{
	int l=1,r=idx;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(vec[mid]==val)
			return mid;
		if(vec[mid]


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