中位数显然是可以二分的,我们二分一个(mid),所有边权不小于(mid)设成(1),否则设为(-1);如果能找到一条边权和不小于(0)的路径,就说明中位数可以更大;于是这显然可以长链剖分+线段树
第一次写长剖线段树,就当写个板子了
代码
#include<bits/stdc++.h>
#define re register
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
const int maxn=1e5+5;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct node{int mx,t;}a[maxn*3];
int l[maxn*3],r[maxn*3],tag[maxn*3];
struct E{int v,nxt,w;}e[maxn<<1];
int dfn[maxn],len[maxn],son[maxn],head[maxn];
int n,num,L,R,rx,ry,X,Y,flag,__,val[maxn],wt[maxn];
inline void add(int x,int y,int w) {
e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=w;
}
void dfs1(int x,int fa) {
for(re int i=head[x];i;i=e[i].nxt) {
if(e[i].v==fa) continue;dfs1(e[i].v,x);
if(len[e[i].v]>len[son[x]]) son[x]=e[i].v,wt[x]=e[i].w;
}
len[x]=len[son[x]]+1;
}
void dfs2(int x) {
dfn[x]=++__;if(!son[x])return;dfs2(son[x]);
for(re int i=head[x];i;i=e[i].nxt)if(!dfn[e[i].v])dfs2(e[i].v);
}
inline node operator+(const node &A,const node &B) {return A.mx>B.mx?A:B;}
void build(int x,int y,int i) {
l[i]=x,r[i]=y;if(x==y)return;
int mid=x+y>>1;build(x,mid,i<<1),build(mid+1,y,i<<1|1);
}
void clr(int i) {
tag[i]=a[i].t=0;a[i].mx=-n;
if(l[i]==r[i])return;clr(i<<1),clr(i<<1|1);
}
inline void mix(int i,int v) {tag[i]+=v;a[i].mx+=v;}
inline void pushdown(int i) {
if(!tag[i])return;
mix(i<<1,tag[i]),mix(i<<1|1,tag[i]);tag[i]=0;
}
node qry(int x,int y,int i) {
if(x<=l[i]&&y>=r[i])return a[i];int mid=l[i]+r[i]>>1;pushdown(i);
if(y<=mid)return qry(x,y,i<<1);if(x>mid)return qry(x,y,i<<1|1);
return qry(x,y,i<<1)+qry(x,y,i<<1|1);
}
void chg(int x,int y,int v,int i) {
if(x<=l[i]&&y>=r[i]) {mix(i,v);return;}
int mid=l[i]+r[i]>>1;pushdown(i);
if(x<=mid)chg(x,y,v,i<<1);if(y>mid)chg(x,y,v,i<<1|1);
a[i]=a[i<<1]+a[i<<1|1];
}
void mof(int pos,int i,node v) {
if(l[i]==r[i]) {a[i]=a[i]+v;return;}
int mid=l[i]+r[i]>>1;pushdown(i);
if(pos<=mid)mof(pos,i<<1,v);else mof(pos,i<<1|1,v);a[i]=a[i<<1]+a[i<<1|1];
}
void Dfs(int x,int fa,int mid) {
if(flag)return;
mof(dfn[x],1,(node){0,x});if(!son[x])return;
Dfs(son[x],x,mid);
chg(dfn[x]+1,dfn[x]+len[x]-1,wt[x]>=mid?1:-1,1);
if(L<len[x]) {
node ask=qry(dfn[x]+L,dfn[x]+min(len[x]-1,R),1);
if(ask.mx>=0) {flag=1;X=x,Y=ask.t;return;}
}
for(re int i=head[x];i;i=e[i].nxt) {
if(e[i].v==fa||e[i].v==son[x])continue;Dfs(e[i].v,x,mid);
int v=(e[i].w>=mid?1:-1);
for(re int j=1;j<=len[e[i].v];++j) {
node c=qry(dfn[e[i].v]+j-1,dfn[e[i].v]+j-1,1);
c.mx+=v;if(L-j>=len[x]||j>R) continue;
node ask=qry(dfn[x]+max(0,L-j),dfn[x]+min(len[x]-1,R-j),1);
if(ask.mx+c.mx>=0) {X=c.t,Y=ask.t;flag=1;return;}
}
for(re int j=1;j<=len[e[i].v];++j) {
node c=qry(dfn[e[i].v]+j-1,dfn[e[i].v]+j-1,1);
c.mx+=v;mof(dfn[x]+j,1,c);
}
}
}
inline int chk(int mid) {
clr(1);flag=0;Dfs(1,0,mid);return flag;
}
int main() {
n=read(),L=read(),R=read();
for(re int x,y,w,i=1;i<n;i++) {
x=read(),y=read(),w=read();
add(x,y,w),add(y,x,w);val[i]=w;
}
dfs1(1,0);dfs2(1);build(1,n,1);std::sort(val+1,val+n);
int rr=std::unique(val+1,val+n)-val-1,ll=1;
while(ll<=rr) {
int mid=ll+rr>>1;
if(chk(val[mid])) {
ll=mid+1;rx=X,ry=Y;
}
else rr=mid-1;
}
printf("%d %d
",rx,ry);return 0;
}