我们根据dfs顺序建立主席树。求树上第k大,对于u到v的一条路径,我们用u的树+v的树,很明显lca(u,v)多算了一次,fa[lca(u,v)]多算了两次,所以用u的树+v的树-lca(u,v)的树-fa[lca(u,v)]的树即可
#include
using namespace std;
#define lson l,m
#define rson m+1,r
const int N = 100100;
int sum[N*20],ls[N*20],rs[N*20],n,m,val[N],id[N],cnt=0,root[N];
vector<int> son[N],v;
int to[N][25],depth[N];
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
int init(int l,int r){
int rt=++cnt;
sum[rt]=0,ls[rt]=rt,rs[rt]=rt;
int m=(l+r)/2;
if(l!=r){
ls[rt]=init(lson);
rs[rt]=init(rson);
}
return rt;
}
void dfs(int now,int fa,int dep){
to[now][0]=fa;
depth[now]=dep;
for(int i=0;iif(son[now][i]!=fa)
dfs(son[now][i],now,dep+1);
}
void initlca(){
for(int i=1;i<20;i++)
for(int j=0;j<=n;j++)
to[j][i]=to[to[j][i-1]][i-1];
}
int lca(int a,int b){
if(depth[a]>depth[b])
swap(a,b);
for(int i=19;i>=0;i--)
if(depth[to[b][i]]>=depth[a])
b=to[b][i];
if(a==b) return a;
for(int i=19;i>=0;i--){
if(to[a][i]!=to[b][i]){
a=to[a][i];
b=to[b][i];
}
}
return to[a][0];
}
int update(int pre,int x,int l, int r){
int rt=(++cnt);
ls[rt]=ls[pre], rs[rt]=rs[pre], sum[rt]=sum[pre]+1;
if(l!=r){
int m=(l+r)>>1;
if(x<=m) ls[rt]=update(ls[pre], x, lson);
else rs[rt]=update(rs[pre], x, rson);
}
return rt;
}
void build(int now,int fa){
root[now]=update(root[fa],getid(val[now]),1,v.size());
for(int i=0;iif(son[now][i]!=fa)
build(son[now][i],now);
}
int query(int u,int v,int lc,int flc,int k,int l,int r){
if(l==r) return l;
int m=(l+r)/2;
int num=sum[ls[u]]+sum[ls[v]]-sum[ls[lc]]-sum[ls[flc]];
if(num>=k)
return query(ls[u],ls[v],ls[lc],ls[flc],k,lson);
return query(rs[u],rs[v],rs[lc],rs[flc],k-num,rson);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
v.push_back(val[i]);
}
v.push_back(0);
sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
for(int i=0,u,v;i1;i++){
scanf("%d%d",&u,&v);
son[u].push_back(v);
son[v].push_back(u);
}
son[0].push_back(1);
son[1].push_back(0);
root[0]=init(1,v.size());
dfs(0,0,1);
initlca();
build(1,0);
while(m--){
int u,vv,k,lc,flc;
scanf("%d%d%d",&u,&vv,&k);
lc=lca(u,vv);
flc=to[lc][0];
printf("%d\n",v[query(root[u],root[vv],root[lc],root[flc],k,1,v.size())-1]);
}
}