luogu P2633 Count on a tree |主席树

题目描述

给定一棵 \(n\) 个节点的树,每个点有一个权值。有 \(m\) 个询问,每次给你 \(u,v,k\),你需要回答 \(u \text{ xor last}\)\(v\) 这两个节点间第 \(k\) 小的点权。

其中 \(\text{last}\) 是上一个询问的答案,定义其初始为 \(0\),即第一个询问的 \(u\) 是明文。

输入格式

第一行两个整数 \(n,m\)

第二行有 \(n\) 个整数,其中第 \(i\) 个整数表示点 \(i\) 的权值。

后面 \(n-1\) 行每行两个整数 \(x,y\),表示点 \(x\) 到点 \(y\) 有一条边。

最后 \(m\) 行每行两个整数 \(u,v,k\),表示一组询问。

输出格式

\(m\) 行,每行一个正整数表示每个询问的答案。


#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5,M=2*N,_=1e7+5;
inline int read(){
	int x=0; char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
	return x;
}
int nxt[M],head[N],go[M],tot;
inline void add(int u,int v){
	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
	nxt[++tot]=head[v],head[v]=tot,go[tot]=u;	
}
int n,m,a[N],b[N];
#define mid ((l+r)>>1)
int root[_],ls[_],rs[_],val[_],cnt;
inline int build(int l,int r){
	int rt=++cnt;
	if(l==r)return rt;
	ls[rt]=build(l,mid);
	rs[rt]=build(mid+1,r);
	return rt;
}
int update(int p,int l,int r,int pos){
	int rt=++cnt;
	ls[rt]=ls[p],rs[rt]=rs[p],val[rt]=val[p]+1;
	if(l==r)return rt;
	if(pos<=mid)ls[rt]=update(ls[p],l,mid,pos);
	else rs[rt]=update(rs[p],mid+1,r,pos);
	return rt;
}
int query(int p1,int p2,int q1,int q2,int l,int r,int k){
	if(l==r)return l;
	int x=val[ls[p1]]-val[ls[p2]]+val[ls[q1]]-val[ls[q2]];
	if(k<=x)return query(ls[p1],ls[p2],ls[q1],ls[q2],l,mid,k);
	else return query(rs[p1],rs[p2],rs[q1],rs[q2],mid+1,r,k-x);
}
int f[N][21],dep[N];
void dfs(int u,int fa){
	dep[u]=dep[fa]+1,f[u][0]=fa;
	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=nxt[i]){
		int v=go[i];
		if(v==fa)continue;
		root[v]=update(root[u],1,n,a[v]);
		dfs(v,u);
	}
}
int LCA(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=20;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
	if(x==y)return x;
	for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)a[i]=b[i]=read();
	sort(b+1,b+1+n);
	int len=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+len,a[i])-b;
	for(int i=1;i<n;i++)add(read(),read());
	root[0]=build(1,n);
	root[1]=update(root[0],1,n,a[1]);
	dfs(1,1);
	f[1][0]=0;
	int u,v,k,lst=0;
	while(m--){
		u=read()^lst,v=read(),k=read();
		int lca=LCA(u,v);
		int ans=query(root[u],root[lca],root[v],root[f[lca][0]],1,n,k);
		printf("%d\n",b[ans]);
		lst=b[ans];
	}
    return 0;
}
posted @ 2020-06-04 14:23  白木偶君  阅读(124)  评论(0编辑  收藏  举报