版权声明:本文为博主原创文章,可以转载但是必须声明版权。 https://blog.csdn.net/forever_shi/article/details/82940987
题目链接
题意:
给你一棵树,m次询问,每次求x,y路径上的第k小值
题解:
首先将权值离散化之后,用主席树维护。主席树中每一棵线段树中记录从该点到根(我规定了1号节点为根)的信息之和,这样求一条链的信息就相当于求x到根+y到根-lca(x,y)到根-father(lca(x,y))到根,这样就可以不重不漏地包含链上每个点的信息一遍,可以自己画个图看看。
其中LCA可以倍增求出,然后我们在询问时要在四棵线段树上同时向下遍历,这样才能保证对应节点之间正确地相加减。
代码自己的写崩了,照着msz的AC代码调的,所以码风可能略奇怪。
#include <bits/stdc++.h>
using namespace std;
int n,m,c[200010],rk[200010],cnt,b[200010],d[200010],hed[200010],num;
int f[200010][21],root[200010],ji[5],dep[200010],lst;
struct node
{
int to,next;
}a[500010];
struct tree
{
int l,r,sz;
}tr[5000010];
inline void add(int from,int to)
{
a[++cnt].to=to;
a[cnt].next=hed[from];
hed[from]=cnt;
}
inline void update(int &rt,int pre,int l,int r,int x)
{
rt=++cnt;
tr[rt].l=tr[pre].l;
tr[rt].r=tr[pre].r;
tr[rt].sz=tr[pre].sz+1;
if(l<r)
{
int mid=(l+r)>>1;
if(x<=mid)
update(tr[rt].l,tr[pre].l,l,mid,x);
else
update(tr[rt].r,tr[pre].r,mid+1,r,x);
}
}
inline void dfs(int x)
{
for(int i=1;i<=20;++i)
{
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i=hed[x];i;i=a[i].next)
{
int y=a[i].to;
if(y!=f[x][0])
{
f[y][0]=x;
dep[y]=dep[x]+1;
update(root[y],root[x],1,n,d[y]);
dfs(y);
}
}
}
inline int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
for(int i=20;i>=0;--i)
{
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
}
if(x==y)
return x;
for(int i=20;i>=0;--i)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
inline int query(int l,int r,int k)
{
if(l==r)
return l;
int sum=tr[tr[ji[1]].l].sz+tr[tr[ji[2]].l].sz-tr[tr[ji[3]].l].sz-tr[tr[ji[4]].l].sz;
int mid=(l+r)>>1;
if(sum>=k)
{
for(int i=1;i<=4;++i)
ji[i]=tr[ji[i]].l;
return query(l,mid,k);
}
else
{
for(int i=1;i<=4;++i)
ji[i]=tr[ji[i]].r;
return query(mid+1,r,k-sum);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&c[i]);
d[i]=c[i];
}
for(int i=1;i<=n-1;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
sort(c+1,c+n+1);
for(int i=1;i<=n;++i)
d[i]=lower_bound(c+1,c+n+1,d[i])-c;
cnt=0;
update(root[1],root[0],1,n,d[1]);
dep[1]=1;
dfs(1);
for(int i=1;i<=m;++i)
{
int x,y,k,gg;
scanf("%d%d%d",&x,&y,&k);
gg=lca(x^lst,y);
ji[1]=root[x^lst];
ji[2]=root[y];
ji[3]=root[gg];
ji[4]=root[f[gg][0]];
lst=c[query(1,n,k)];
printf("%d\n",lst);
}
return 0;
}