码迷,mamicode.com
首页 > 其他好文 > 详细

【主席树】bzoj2588 Spoj 10628. Count on a tree

时间:2015-04-13 20:40:23      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

每个点的主席树的root是从其父转移来的。询问的时候用U+V-LCA-FA(LCA)即可。

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100001
int v[N<<1],first[N],next[N<<1],en,Ans;
void AddEdge(int U,int V)
{
	v[++en]=V;
	next[en]=first[U];
	first[U]=en;
}
struct Point{int v,p;}t[N];
bool operator < (Point a,Point b){return a.v<b.v;}
int n,m,ma[N],a[N],zy;
struct Node{int v,lc,rc;}T[N*24];
int root[N],e=1;
void BuildTree(int cur,int l,int r)
{
	if(l==r) return;
	int m=(l+r>>1);
	T[cur].lc=++e;
	BuildTree(T[cur].lc,l,m);
	T[cur].rc=++e;
	BuildTree(T[cur].rc,m+1,r);
}
void Insert(int pre,int cur,int p,int l,int r)
{
	if(l==r)
	  {
	  	T[cur].v=T[pre].v+1;
	  	return;
	  }
	int m=(l+r>>1);
	if(p<=m)
	  {
	  	T[cur].lc=++e;
	  	T[cur].rc=T[pre].rc;
	  	Insert(T[pre].lc,T[cur].lc,p,l,m);
	  }
	else
	  {
	  	T[cur].rc=++e;
	  	T[cur].lc=T[pre].lc;
	  	Insert(T[pre].rc,T[cur].rc,p,m+1,r);
	  }
	T[cur].v=T[T[cur].lc].v+T[T[cur].rc].v;
}
int top[N],siz[N],son[N],fa[N],dep[N];
void df1(int U)
{
	siz[U]=1;
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=fa[U])
	    {
	      fa[v[i]]=U;
	      dep[v[i]]=dep[U]+1;
	      df1(v[i]);
	      siz[U]+=siz[v[i]];
	      if(siz[v[i]]>siz[son[U]])
	        son[U]=v[i];
	    }
}
void df2(int U)
{
	if(son[U])
	  {
	  	top[son[U]]=top[U];
	  	df2(son[U]);
	  }
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=fa[U]&&v[i]!=son[U])
	    {
	      top[v[i]]=v[i];
	      df2(v[i]);
	    }
}
int lca(int U,int V)
{
	while(top[U]!=top[V])
	  {
	  	if(dep[top[U]]<dep[top[V]])
	  	  swap(U,V);
	  	U=fa[top[U]];
	  }
	if(dep[U]>dep[V])
	  swap(U,V);
	return U;
}
void dfs(int U)
{
	root[U]=++e;
	Insert(root[fa[U]],root[U],a[U],1,zy);
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=fa[U])
	    dfs(v[i]);
}
int Kth(int ql,int qr,int LCA,int FLCA,int K,int l,int r)
{
	if(l==r) return l;
	int m=(l+r>>1);
	if(T[T[ql].lc].v+T[T[qr].lc].v-T[T[LCA].lc].v-T[T[FLCA].lc].v>=K)
	  return Kth(T[ql].lc,T[qr].lc,T[LCA].lc,T[FLCA].lc,K,l,m);
	else
	  return Kth(T[ql].rc,T[qr].rc,T[LCA].rc,T[FLCA].rc,K-(T[T[ql].lc].v+T[T[qr].lc].v-T[T[LCA].lc].v-T[T[FLCA].lc].v),m+1,r);
}
int main()
{
	int X,Y,W;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	  {
	  	scanf("%d",&t[i].v);
	  	t[i].p=i;
	  }
	sort(t+1,t+n+1);
	a[t[1].p]=++zy;
	ma[zy]=t[1].v;
	for(int i=2;i<=n;++i)
	  {
	  	if(t[i].v!=t[i-1].v) ++zy;
	  	a[t[i].p]=zy;
	  	ma[zy]=t[i].v;
	  }
	for(int i=1;i<n;++i)
	  {
	  	scanf("%d%d",&X,&Y);
	  	AddEdge(X,Y);
	  	AddEdge(Y,X);
	  }
	root[0]=1;
	BuildTree(root[0],1,zy);
	df1(1);
	top[1]=1;
	df2(1);
	dfs(1);
	for(;m;--m)
	  {
	  	scanf("%d%d%d",&X,&Y,&W); X^=Ans;
	  	int t=lca(X,Y);
	  	printf("%d",Ans=ma[Kth(root[X],root[Y],root[t],root[fa[t]],W,1,zy)]);
	    if(m!=1) puts("");
	  }
	return 0;
}

【主席树】bzoj2588 Spoj 10628. Count on a tree

标签:

原文地址:http://www.cnblogs.com/autsky-jadek/p/4422979.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!