BZOJ 2588 Spoj 10628. Count on a tree

题解:主席树,上一层为父亲节点对应的主席树

查询就用 u+v-lca-fa[lca]即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200009;

int n,m;
int lastans;
int v[maxn];
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int b[maxn],nn;
int root[maxn];
int PTsiz;
struct PresidentTree{
	int l,r,d,ls,rs;
}tree[maxn*20];
void BuildTree(int &now,int l,int r){
	now=++PTsiz;
	tree[now].l=l;tree[now].r=r;tree[now].d=0;
	if(l==r)return;
	int mid=(l+r)>>1;
	BuildTree(tree[now].ls,l,mid);
	BuildTree(tree[now].rs,mid+1,r);
}
void Updatapoint(int &now,int pre,int p){
	now=++PTsiz;
	tree[now]=tree[pre];
	tree[now].d++;
	if(tree[now].l==tree[now].r)return;
	int mid=(tree[now].l+tree[now].r)>>1;
	if(p<=mid)Updatapoint(tree[now].ls,tree[pre].ls,p);
	else Updatapoint(tree[now].rs,tree[pre].rs,p);
}
int Querykth(int x,int y,int z,int w,int k){
	if(tree[x].l==tree[x].r)return b[tree[x].l];
	int d=tree[tree[x].ls].d+tree[tree[y].ls].d-tree[tree[z].ls].d-tree[tree[w].ls].d;
	if(k<=d)return Querykth(tree[x].ls,tree[y].ls,tree[z].ls,tree[w].ls,k);
	else return Querykth(tree[x].rs,tree[y].rs,tree[z].rs,tree[w].rs,k-d);
}

int f[maxn][20];
int depth[maxn];
void Dfs(int now,int fa){
	f[now][0]=fa;
	depth[now]=depth[fa]+1;
	int p=lower_bound(b+1,b+1+nn,v[now])-b;
	Updatapoint(root[now],root[fa],p);
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dfs(to[i],now);
	}
}

void LCAinit(){
	for(int j=1;j<=19;++j){
		for(int i=1;i<=n;++i){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
}
int Querylca(int u,int v){
	if(depth[u]<depth[v])swap(u,v);
	for(int j=19;j>=0;--j){
		if(depth[f[u][j]]>=depth[v])u=f[u][j];
	}
	if(u==v)return u;
	for(int j=19;j>=0;--j){
		if(f[u][j]!=f[v][j]){
			u=f[u][j];v=f[v][j];
		}
	}
	return f[u][0];
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&v[i]);b[i]=v[i];
	}
	sort(b+1,b+1+n);
	nn=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n-1;++i){
		int x,y;scanf("%d%d",&x,&y);
		Addedge(x,y);Addedge(y,x);
	}
	
	BuildTree(root[0],1,n);
	Dfs(1,0);
	LCAinit();
	
	while(m--){
		int u,v,k;
		scanf("%d%d%d",&u,&v,&k);
		u^=lastans;
		int lca=Querylca(u,v);
		printf("%d",lastans=Querykth(root[u],root[v],root[lca],root[f[lca][0]],k));
		if(m!=0)printf("\n");
	}
	return 0;
}

  

posted @ 2018-02-21 11:43  ws_zzy  阅读(185)  评论(0编辑  收藏  举报