题目大意:给定一棵n个点的树,每个点有一个权值,m个询问,每次询问树上点x到点y的路径上的第k小数。
思路:dfs后给每个节点一个dfs序,以每个点在他父亲的基础上建立主席树,询问时用(点x+点y-点lca(x,y)-点dad[lca(x,y)])即可得到x到y的链,在上面查询即可。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 200009
using namespace std;
int tot=1,dfn,num,cnt,pa[N][18],to[N],next[N],head[N],lc[N*10],rc[N*10],deep[N],sum[N*10],id[N],pos[N],root[N],a[N],b[N];
int read()
{
int x=0,y=1;char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') y=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*y;
}
void add(int x,int y)
{
to[++cnt]=y,next[cnt]=head[x],head[x]=cnt;
}
void dfs(int x)
{
int i;id[x]=++dfn,pos[dfn]=x;
for (i=1;i<=16;i++)
if ((1<<i)<=deep[x]) pa[x][i]=pa[pa[x][i-1]][i-1];
else break;
for (i=head[x];i;i=next[i])
if (pa[x][0]!=to[i])
{
deep[to[i]]=deep[x]+1;
pa[to[i]][0]=x;
dfs(to[i]);
}
}
void change(int l,int r,int x,int &cur,int _cur)
{
cur=++num;
lc[cur]=lc[_cur];
rc[cur]=rc[_cur];
sum[cur]=sum[_cur]+1;
if (l==r) return;
int mid=l+r>>1;
if (x<=b[mid]) change(l,mid,x,lc[cur],lc[_cur]);
else change(mid+1,r,x,rc[cur],rc[_cur]);
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int i,t=deep[x]-deep[y];
for (i=0;i<=16;i++)
if ((1<<i)&t) x=pa[x][i];
for (i=16;i>=0;i--)
if (pa[x][i]!=pa[y][i]) x=pa[x][i],y=pa[y][i];
if (x==y) return x;
return pa[x][0];
}
int ask(int x,int y,int k)
{
int a=root[id[x]],b=root[id[y]],c=LCA(x,y),d=pa[c][0],l=1,r=tot;
c=root[id[c]],d=root[id[d]];
while (l<r)
{
int t=sum[lc[a]]+sum[lc[b]]-sum[lc[c]]-sum[lc[d]],mid=l+r>>1;
if (t>=k) a=lc[a],b=lc[b],c=lc[c],d=lc[d],r=mid;
else a=rc[a],b=rc[b],c=rc[c],d=rc[d],l=mid+1,k-=t;
}
return l;
}
int main()
{
int n=read(),m=read(),i,x,y,ans=0,k;
for (i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
for (i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
dfs(1),sort(b+1,b+n+1);
for (i=2;i<=n;i++)
if (b[tot]!=b[i]) b[++tot]=b[i];
for(i=1;i<=n;i++) change(1,tot,a[pos[i]],root[i],root[id[pa[pos[i]][0]]]);
for (i=1;i<=m;i++)
{
x=read(),y=read(),k=read(),x^=ans;
printf("%d",ans=b[ask(x,y,k)]);
if (i<m) printf("\n");
}
return 0;
}