BZOJ 2588

http://www.lydsy.com/JudgeOnline/problem.php?id=2588

在树上建主席树

每个节点按它的father建一颗新树

对于路径(u,v)等价于(1,u)+(1,v)-(1,lca(u,v))-(1,fa[lca(u,v)])

root[u],root[v],root[lca(u,v)],root[fa[lca(u,v)]]

然后在这4棵主席树上差分,取出k小值

#include<cstdio>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
const int N=100011,NlogN=2000011;
struct Tree{
	int ls,rs,sum;
	#define ls(now) (tr[now].ls)
	#define rs(now) (tr[now].rs)
	#define sum(now) (tr[now].sum)
}tr[NlogN];
int rt[N];
int n,m,ans,a[N],b[N];
int x,y,p,k,cnt;
inline void disc_init(){
	sort(b+1,b+b[0]+1);
	b[0]=unique(b+1,b+b[0]+1)-b-1;
	FOR(i,1,n)a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
}
struct edge{
	int to;edge *nxt;
	#define VIS(now) for(edge *it=las[now];it;it=it->nxt)
	#define to(it) (it->to)
}e[N<<1],*las[N],*tot=e;
int top[N],fa[N],dep[N],sz[N];
inline void add(int x,int y){
	*++tot=(edge){y,las[x]},las[x]=tot;
}
inline void dfs1(int now){
	int to;sz[now]=1;
	VIS(now)
		if(!dep[to(it)]){
			dep[to(it)]=dep[now]+1;fa[to(it)]=now;
			dfs1(to(it));sz[now]+=sz[to(it)];
		}
}
inline void build(int cpy,int &now,int l,int r,int pos){
	tr[now=++cnt]=tr[cpy];++sum(now);
	if(l==r)return;int mid=(l+r)>>1;
	pos<=mid?build(ls(cpy),ls(now),l,mid,pos):build(rs(cpy),rs(now),mid+1,r,pos);
}
inline int query(int a,int b,int c,int d,int l,int r,int k){
	if(l==r)return l;
	int data=sum(ls(a))+sum(ls(b))-sum(ls(c))-sum(ls(d));
	int mid=(l+r)>>1;
	return k<=data?query(ls(a),ls(b),ls(c),ls(d),l,mid,k):query(rs(a),rs(b),rs(c),rs(d),mid+1,r,k-data);
}
inline void dfs2(int now,int chain){
	top[now]=chain;build(rt[fa[now]],rt[now],1,b[0],a[now]);
	register int i=0;
	VIS(now)if(fa[now]!=(to(it))&&sz[to(it)]>sz[i])i=to(it);
	if(!i)return;dfs2(i,chain);
	VIS(now)if(fa[now]!=(to(it))&&i!=to(it))dfs2(to(it),to(it));
}
inline int lca(int x,int y){
	for(;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
	return dep[x]<dep[y]?x:y;
}
int main(){
	scanf("%d%d",&n,&m);
	FOR(i,1,n)scanf("%d",a+i),b[++b[0]]=a[i];
	disc_init();
	FOR(i,2,n){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dep[1]=1;dfs1(1);dfs2(1,1);
	while(m--){
		scanf("%d%d%d",&x,&y,&k);
		x^=ans;p=lca(x,y);
		ans=b[query(rt[x],rt[y],rt[p],rt[fa[p]],1,b[0],k)];
		printf("%d",ans);
		if(m)putchar('\n');
	}
	return 0;
}

  

posted @ 2017-12-03 20:12  Stump  阅读(221)  评论(0编辑  收藏  举报