[没有链接]
JBT is going to climb the mountain, but he was suddenly trapped into an unknown enchantment.
There are n mountains, connected by n−1 paths. There is only one road between any two mountains. Each mountain has a height h. In order to leave this enchantment, he has to answer m questions, for each question JBT should answer the height of the kth-highest mountain passed by on the road from the mountain u to the mountain v,and JBT cannot travel through the same mountain twice.
JBT is very worried that he will never be able to get out of this enchantment, so he wants you to help him.
The first line contains one integer T indicate the number of tests.
The second line contains two integers n and m (1≤n,m≤105).
The third line contains n integers h1,h2,h3…hn (1≤hi≤105).
Each of the next n−1 lines contains two integers u and v (1≤u,v≤n), which means there is a road between ui and vi.
Each of the next m lines contains three integers u, v and k (1≤u,v,k≤n).
For each of query, print the height of the kth-highest mountain in a single line.
If k is bigger than the distance between u and v, please output −1;
1
8 4
1 2 3 4 5 6 7 8
1 2
1 3
2 4
2 5
3 6
3 7
3 8
4 5 2
4 6 3
5 3 2
2 3 3
4
3
3
1
给出n点的一棵树,树上每点有权值,求u到v的路径上的第k大
经典题,不过是第一次遇到大概写了1h+,果然不经常用的算法就是容易忘啊,还好自己写板子比较容易理解,还是贴一下代码吧
在树上构造主席树,每个点记录该点到根路径上所有点。u-v的路径上的点就是 u+v-lca(u,v)-father[lca(u,v)]
(因为建树的时候直接从1到n建wa了一发,应该保证父节点已经建过树的)
#include
#define LL long long
using namespace std;
const LL maxn=1e5+7;
int n,m;///m为hash后的数据范围
int b[maxn];///hash过的数据
int tree[maxn];///tree[i]为第i个版本的根节点
int tot;///用来表示建了多少节点
int val[maxn];
vector <int> edge[maxn];
int fa[maxn];///父
int depth[maxn];///深度,根为1
int vis[maxn];
struct node
{
int v;///节点值
int lc,rc;///左右子树
}t[maxn*22];
void init_hash()
{
for(int i=1;i<=n;i++)
b[i]=val[i];
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
///unique可以把相同元素集中到数组前面,返回最后一个数的后一个位置
}
int get_pos(int x)
{
return lower_bound(b+1,b+1+m,x)-b;
}
int build(int l,int r)
{
int root=tot++;
t[root].v=0;
if(l!=r)
{
int mid=(l+r)/2;
t[root].lc=build(l,mid);
t[root].rc=build(mid+1,r);
}
return root;
}
int update(int root,int l,int r,int x,int v)
{
///每次update生成一个新的节点,是从根到需要更新的那个叶子的路径,其他节点与上一个版本完全相同
int newroot=tot++;
t[newroot]=t[root];
t[newroot].v+=v;
if(l==r)
{
return newroot;
}
int mid=(l+r)/2;
if(x>mid)
{
t[newroot].rc=update(t[root].rc,mid+1,r,x,v);
}
else
{
t[newroot].lc=update(t[root].lc,l,mid,x,v);
}
return newroot;
}
int query(int l1,int r1,int l2,int r2,int k,int li,int ri)
{
///l1,l2,r1,r2分别是多个版本里的相同节点
///li和ri只是用来帮助确定节点表示的范围的
//printf("(%d,%d) %d %d %d\n",li,ri,t[l].v,t[r].v,k);
if(li==ri) return li;
int cl1=t[l1].lc,cl2=t[l2].lc,cr1=t[r1].lc,cr2=t[r2].lc;
if(t[cl1].v+t[cr1].v-t[cl2].v-t[cr2].v>=k)
{
return query(cl1,cr1,cl2,cr2,k,li,(li+ri)/2);
}
else
{
return query(t[l1].rc,t[r1].rc,t[l2].rc,t[r2].rc,k-(t[cl1].v+t[cr1].v-t[cl2].v-t[cr2].v),(li+ri)/2+1,ri);
}
// int l1=t[l].lc,l2=t[r].lc;
// if(t[l2].v-t[l1].v>=k)
// {
// return query(l1,l2,k,li,(li+ri)/2);
// }
// else
// {
// return query(t[l].rc,t[r].rc,k-t[l2].v+t[l1].v,(li+ri)/2+1,ri);
// }
}
//void dfs(int root,int l,int r)
//{
// printf("(%d,%d,%d) ",l,r,t[root].v);
// if(l==r) return;
// int mid=(l+r)/2;
// dfs(t[root].lc,l,mid);
// dfs(t[root].rc,mid+1,r);
//}
void dfs(int x, int d)///初始化为(1,1)
{
vis[x]=1;
depth[x]=d;
d++;
for(int i=0;i<edge[x].size();i++)
{
if(vis[edge[x][i]]==0)
{
fa[edge[x][i]]=x;
dfs(edge[x][i], d);
}
}
}
int preLCA[maxn][19];
void pre_lca()
{
int i,j;
j=0;
for(i=1;i<=n;i++)
preLCA[i][0]=fa[i];
for(i=1;i<=n;i++)
for(j=1;j<19;j++)
preLCA[i][j]=preLCA[preLCA[i][j-1]][j-1];
}
int lca(int u,int v)
{
int i;
if(depth[u]<depth[v]) swap(u,v);
for(i=18;i>=0;i--) if(depth[preLCA[u][i]]>=depth[v]) u=preLCA[u][i];
for(i=18;i>=0;i--) if(preLCA[u][i]!=preLCA[v][i]) u=preLCA[u][i],v=preLCA[v][i];
if(u!=v) return fa[u];
else return u;
}
void dfs2(int x)
{
vis[x]=1;
int y=get_pos(val[x]);
tree[x]=update(tree[fa[x]],1,m,y,1);
for(int i=0;i<edge[x].size();i++)
{
if(vis[edge[x][i]]==0)
{
dfs2(edge[x][i]);
}
}
}
int main()
{
int q,T,i,j,k,x,y,l,r,len;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&val[i]);
edge[i].clear();
vis[i]=0;
}
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(1,1);
init_hash();
tot=0;
tree[0]=build(1,m);
for(i=1;i<=n;i++)
{
vis[i]=0;
}
dfs2(1);
// for(i=0;i<=n;i++)
// {
// dfs(tree[i],1,m);
// printf("\n");
// }
pre_lca();
for(i=1;i<=q;i++)
{
scanf("%d%d%d",&l,&r,&k);
x=lca(l,r);
len=depth[l]+depth[r]-depth[x]-depth[fa[x]];
//printf("len=%d\n",len);
//printf("x=%d\n",x);
if(len<k)
{
printf("-1\n");
continue;
}
k=len-k+1;
//printf("k=%d\n",k);
//printf("(%d,%d,%d,%d)\n",l,r,x,fa[x]);
x=query(tree[l],tree[r],tree[x],tree[fa[x]],k,1,m);
//printf("query=%d\n",x);
printf("%d\n",b[x]);
}
}
return 0;
}
/**
1
3 1
3 2 1
1 2
2 3
2 3 1
2
3 5
3 2 1
1 2
2 3
1 2 1
1 2 2
1 2 3
2 3 1
1 3 3
8 10
1 2 3 4 5 6 7 8
1 2
1 3
2 4
2 5
3 6
3 7
3 8
4 5 2
4 6 3
5 3 2
2 3 3
**/