题意
给一棵树,问树上路径权值中位数。
题解
树上路径权值中位数就是求第k/2大数,很明显主席树+LCA。这道题还是比较容易的,有一点非常重要的是权值W的范围是1-100000,这个范围很大程度上影响了题目的实现难度。由于权值最大只有10万,因此我们可以搞一个10万的主席树,这样的话每一次查询第K大,我们可以利用主席树去针对某一段版本的线段树去查询,从右到左的第K的数字就是第K大。
搞明白了这个,还有一个需要搞明白的就是树上的查询需要用v[a]+v[b]-2*v[lca(a,b)]。这样一减求的就是路径上的值。
代码
#include<bits/stdc++.h>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define LL long long
#define INF 0x3f3f3f3f
#define EPS 1e-8
#define MAXN 50010
#define MOD 100000007
#define COUT(x) cout<<x<<endl
using namespace std;
struct Edge{
int to,w;
Edge(int to=0,int w=0):to(to),w(w){}
};
vector<Edge> vc[MAXN];
const int NN=25001000;
int dep[MAXN],sum[NN],ln[NN],rn[NN],root[MAXN];
int anc[MAXN][25];
int tot;
int update(int o,int L,int l,int r)
{
// COUT(o<<" "<<l<<" "<<r);
int k=++tot;
sum[k]=sum[o],ln[k]=ln[o],rn[k]=rn[o];
sum[k]++;
if(l==r) return k;
int m=(l+r)/2;
if(L<=m) ln[k]=update(ln[k],L,l,m);
else rn[k]=update(rn[k],L,m+1,r);
return k;
}
int query(int a,int b,int f,int L,int l,int r)
{
if(l==r) return l;
int m=(l+r)/2;
int tmp=(sum[ln[b]]+sum[ln[a]]-2*sum[ln[f]]);
if(L<=tmp) return query(ln[a],ln[b],ln[f],L,l,m);
else return query(rn[a],rn[b],rn[f],L-tmp,m+1,r);
}
void dfs(int u,int f,int deep){
// COUT("dfs"<<u);
dep[u]=deep;
anc[u][0]=f;
// COUT(u<<" "<<f);
UP(i,1,20){
anc[u][i]=anc[anc[u][i-1]][i-1];
}
for(Edge v:vc[u]){
if(f==v.to) continue;
root[v.to]=update(root[u],v.w,1,100000);
dfs(v.to,u,deep+1);
}
}
int lca(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
// COUT(a<<" "<<b);
DOWN(i,20,0){
// COUT(dep[anc[a][i]]<<" "<<dep[b]);
if(dep[b]<=dep[anc[a][i]]) a=anc[a][i];
}
// COUT(a<<" "<<b);
if(a==b) return a;
DOWN(i,20,0){
if(anc[a][i]!=anc[b][i]){
a=anc[a][i];
b=anc[b][i];
}
}
return anc[a][0];
}
int main(){
int t;
scanf("%d",&t);
W(t--){
MEM(vc,0);
MEM(anc,0);
MEM(dep,0);
MEM(sum,0);
MEM(ln,0);
MEM(rn,0);
MEM(root,0);
tot=0;
int n,q;
scanf("%d",&n);
UP(i,0,n-1){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
vc[u].push_back(Edge(v,w));
vc[v].push_back(Edge(u,w));
}
scanf("%d",&q);
dfs(1,0,1);
W(q--){
int a,b;
scanf("%d%d",&a,&b);
int fa=lca(a,b);
// COUT(dep[a]<<" "<<dep[b]);
// COUT(fa);
int cot=dep[a]+dep[b]-2*dep[fa];
// COUT(cot);
if(cot%2==1){
printf("%.1f\n",(double)query(root[a],root[b],root[fa],(cot+1)/2,1,100000));
}else{
// COUT((double)query(root[a],root[b],root[fa],cot/2,1,100000)<<" "<<(double)query(root[a],root[b],root[fa],cot/2+1,1,100000));
printf("%.1f\n",((double)query(root[a],root[b],root[fa],cot/2,1,100000)+(double)query(root[a],root[b],root[fa],cot/2+1,1,100000))/2);
}
}
}
}