【描述】
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
【输入】
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问
【输出】
M行,表示每个询问的答案。最后一个询问不输出换行符
【思路】
我们先来考虑序列第k大。我们查询[l,r]的情况,变成查询r和l-1。那么树上也可以类似操作。我们在每个节点维护其到根节点的信息。路径上的信息可以通过
得到。所以我们只需要同时在四个点对应的树上查询即可。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define re register
using namespace std;
const int N=1e5+5;
int n,m,a,b,k,c[N],val[N],tot,rt[N],las;
tr1::unordered_map<int,int>f;
inline int red()
{
int data=0;int w=1; char ch=0;
ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
namespace tree{
int ch[N*30|1][2],siz[N*30|1],cnt=0;
int change(int v,int l,int r,int pos)
{
int u=++cnt;siz[u]=siz[v]+1;
if(l==r)return cnt;
int mid=(l+r)>>1;
ch[u][0]=ch[v][0];ch[u][1]=ch[v][1];
if(pos<=mid)ch[u][0]=change(ch[v][0],l,mid,pos);
else ch[u][1]=change(ch[v][1],mid+1,r,pos);
return u;
}
int query(int a,int b,int c,int d,int l,int r,int k)
{
if(l==r)return l;
int ls=siz[ch[a][0]]+siz[ch[b][0]]-siz[ch[c][0]]-siz[ch[d][0]];
int mid=(l+r)>>1;
if(ls>=k)return query(ch[a][0],ch[b][0],ch[c][0],ch[d][0],l,mid,k);
else return query(ch[a][1],ch[b][1],ch[c][1],ch[d][1],mid+1,r,k-ls);
}
}
using tree::change;
using tree::query;
namespace LCA{
vector<int>g[N];
int dep[N]={0,1},fa[N][18];
void dfs(int u){
rt[u]=change(rt[fa[u][0]],1,tot,f[val[u]]);
for(int re i=1;(1<<i)<=(dep[u]);i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int re i=g[u].size()-1;~i;--i){int v=g[u][i];if(!dep[v])dep[v]=dep[u]+1,fa[v][0]=u,dfs(v);}
}
inline int lca(int a,int b)
{
if(dep[a]<dep[b])swap(a,b);
int t=dep[a]-dep[b];
for(int re i=0;(1<<i)<=t;++i)
if(t&(1<<i))a=fa[a][i];
if(a==b)return a;
for(int re i=17;~i;--i)
if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
return fa[a][0];
}
}
using LCA::g;
using LCA::dfs;
using LCA::lca;
int main()
{
n=red();m=red();
for(int re i=1;i<=n;i++)c[i]=val[i]=red();
sort(c+1,c+(tot=n)+1);tot=unique(c+1,c+n+1)-c-1;
for(int re i=1;i<=tot;i++)f[c[i]]=i;
for(int re i=1;i^n;i++)a=red(),b=red(),g[a].push_back(b),g[b].push_back(a);dfs(1);
while(m--){
a=red()^las;b=red();k=red();int lc1=lca(a,b),lc2=LCA::fa[lc1][0];
printf("%d",las=c[query(rt[a],rt[b],rt[lc1],rt[lc2],1,tot,k)]);if(m)putchar('\n');
}
}