BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

题意:

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

 

分析:

每个结点开线段树,保存到根这段路径上的权值,然后类似树上差分在主席树上求第k小

 

代码:

 

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
int head[N],to[N<<1],nxt[N<<1];
int top[N],fa[N],dep[N],son[N],siz[N],tot,cnt;
int n,m,root[N],t[N*50],ls[N*50],rs[N*50],a[N],see;
struct A{
	int num,id,v;
}d[N];
bool cmp1(const A &x,const A &y){return x.num<y.num;}
bool cmp2(const A &x,const A &y){return x.id<y.id;}
inline void add(int u,int v){
	to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void rd(int &x){
	int f=1;x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f;
}
void dfs1(int x){
	siz[x]=1;
	for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]){
		fa[to[i]]=x;dep[to[i]]=dep[x]+1;
		dfs1(to[i]);
		siz[x]+=siz[to[i]];
		if(siz[to[i]]>siz[son[x]])son[x]=to[i];
	}
}
void dfs2(int x,int t){
	top[x]=t;
	if(son[x])dfs2(son[x],t);
	for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]&&to[i]!=son[x])dfs2(to[i],to[i]);
}
int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>dep[top[y]])swap(x,y);
		y=fa[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}
void insert(int x,int &y,int l,int r,int val){
	y=++tot;
	if(l==r){t[y]=t[x]+1;return ;}
	int mid=l+r>>1;
	if(val<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,val);
	else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,val);
	t[y]=t[ls[y]]+t[rs[y]];
}
int query(int x,int y,int lca,int f,int l,int r,int k){
	if(l==r)return a[l];
	int mid=l+r>>1,sizls=t[ls[x]]+t[ls[y]]-t[ls[lca]]-t[ls[f]];
	if(k<=sizls) return query(ls[x],ls[y],ls[lca],ls[f],l,mid,k);
	else return query(rs[x],rs[y],rs[lca],rs[f],mid+1,r,k-sizls);
}
void build(int x){
	for(int i=head[x];i;i=nxt[i]){
		if(to[i]!=fa[x]){
			insert(root[x],root[to[i]],1,n,d[to[i]].v);
			build(to[i]);
		}
	}
}
int main(){
	rd(n);rd(m);
	int i,x,y,k,j;
	for(i=1;i<=n;i++) rd(d[i].num),d[i].id=i;
	sort(d+1,d+n+1,cmp1);
	d[0].num=-1000000;
	for(j=0,i=1;i<=n;i++){if(d[i].num!=d[i-1].num)j++;d[i].v=j;a[j]=d[i].num;}
	sort(d+1,d+n+1,cmp2);
	for(i=1;i<n;i++) {
		rd(x);rd(y);
		add(x,y);add(y,x);
	}
	dep[1]=1;fa[1]=0;
	dfs1(1);dfs2(1,1);
	int ans=0;
	//for(i=1;i<=n;i++) insert(root[fa[a[i]]],root[a[i]],minn,maxn,v[a[i]]);
	insert(root[0],root[1],1,n,d[1].v);
	build(1);
	for(i=1;i<=m;i++) {
		scanf("%d%d%d",&x,&y,&k);x^=ans;
		int lca=LCA(x,y);
		ans=query(root[x],root[y],root[lca],root[fa[lca]],1,n,k);
		if(i<m)
		printf("%d\n",ans);
		else printf("%d",ans);
	}
}

 

posted @ 2018-03-18 11:05  fcwww  阅读(131)  评论(0编辑  收藏  举报