luogu P2633 Count on a tree |主席树

题目描述

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

其中 ( ext{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
",b[ans]);
		lst=b[ans];
	}
    return 0;
}
原文地址:https://www.cnblogs.com/naruto-mzx/p/13043268.html