题目链接:https://www.spoj.com/problems/COT/
题意:求u到v节点中第k大的数
思路:每次沿着父亲节点建一颗新的树,用lca的树与两节点的树寻找第k大
/*
SPOJ - COT
一棵树,n个节点,m个询问,a1...an表示节点的权,n-1条边,u,v,k询问u和v路径上第k大的数
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2
ans:
2
8
9
105
7
思路:每次沿着父亲节点建一颗新的树,用lca的树与两节点的树寻找第k大
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define M 100010
using namespace std;
int n,m,cut,tot,tim,len_disc;
int V[M],head[M],num[2*M],ver[2*M],first[M],root[M],disc[M],far[M];
int dp[2*M][32];
struct edge
{
int to,nextt;
}E[2*M];
struct segment_tire
{
int l,r,sum;
segment_tire(int _l=0,int _r=0,int _sum=0):l(_l),r(_r),sum(_sum){};
}T[20*M];
void init()//初始化
{
T[0]=segment_tire(0,0,0);
root[0]=0;
cut=0,tot=0,tim=0;
memset(head,-1,sizeof(head));
}
/********邻接表*********/
void add(int from,int to)
{
E[++cut].to=to;
E[cut].nextt=head[from];
head[from]=cut;
}
/********在线LCA*********/
void dfs(int u,int fa,int tep)
{
first[u]=++tot;
num[tot]=tep;
ver[tot]=u;
for(int i=head[u];i!=-1;i=E[i].nextt)
{
int v=E[i].to;
if(v==fa) continue;
dfs(v,u,tep+1);
num[++tot]=tep;
ver[tot]=u;
}
}
void ST()
{
for(int i=1;i<=tot;i++) dp[i][0]=i;
for(int j=1;(1<<j)<=tot;j++)
{
for(int i=1;i+(1<<j)-1<=tot;i++)
{
int a=dp[i][j-1],b=dp[i+(1<<j-1)][j-1];
dp[i][j]=num[a]<num[b]?a:b;
}
}
}
int RMQ(int u,int v)
{
int l=first[u],r=first[v],k=0;
if(l>r) swap(l,r);
while(1<<(k+1)<=r-l+1) ++k;
int a=dp[l][k],b=dp[r-(1<<k)+1][k];
return num[a]<num[b]?ver[a]:ver[b];
}
/********主席树*********/
void init_disc()
{
for(int i=1;i<=n;i++) disc[i]=V[i];
sort(disc+1,disc+1+n);
len_disc=unique(disc+1,disc+1+n)-disc-1;
}
int discate(int x)
{
return lower_bound(disc+1,disc+1+n,x)-disc;
}
void update(int &rt,int old,int pos,int l,int r)
{
T[++tim]=T[old];
rt=tim;
T[rt].sum+=1;
if(l==r) return ;
int mid=(l+r)>>1;
if(pos<=mid) update(T[rt].l,T[old].l,pos,l,mid);
else update(T[rt].r,T[old].r,pos,mid+1,r);
}
void build_tire(int u,int fa)
{
int d=discate(V[u]);
update(root[u],root[fa],d,1,n);
far[u]=fa;
for(int i=head[u];i!=-1;i=E[i].nextt)
{
int v=E[i].to;
if(v==fa) continue;
build_tire(v,u);
}
}
int query(int u,int v,int lca,int Flca,int k,int l,int r)
{
if(l==r) return l;
int mid=(l+r)>>1;
int d=T[T[u].l].sum+T[T[v].l].sum-T[T[lca].l].sum-T[T[Flca].l].sum;
if(k<=d) return query(T[u].l,T[v].l,T[lca].l,T[Flca].l,k,l,mid);
else return query(T[u].r,T[v].r,T[lca].r,T[Flca].r,k-d,mid+1,r);
}
int main()
{
int u,v,k;
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&V[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,-1,1);
ST();
init_disc();
build_tire(1,0);
while(m--)
{
scanf("%d%d%d",&u,&v,&k);
int lca=RMQ(u,v);
int ans=query(root[u],root[v],root[lca],root[far[lca]],k,1,n);
printf("%d\n",disc[ans]);
}
}