题目描述
给定一棵 (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;
}