版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/85175429
Description
给定一棵带边权的树,求与x第k近的距离,n<=1e5
Solution
之前碰见过。。当时还不会做的
有一道弱化版的n才1.5e4,可以考虑离线然后区间加、区间第k大,卡一卡说不定能过(滑稽
对于求第k大的问题我们经常考虑二分答案变成判定性问题。建出点分树后每个点开两个vector分别记录到x子树内的点到x的所有距离,x子树内点到fa[x]的所有距离。我们把vector排序然后用二分粗来的答案扔进去二分就行了
这样做是3个log的,每个点只会被塞进log个vector中因此这个暴力非常的优秀。
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=200000;
struct edge {int y,w,next;} e[N*2];
int dis[N],dep[N],bl[N],size[N],mx[N];
int ls[N],fa[N],acs[N],edCnt,root,sum;
std:: vector <int> vec1[N],vec2[N];
bool del[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y,int w) {
e[++edCnt]=(edge) {y,w,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,w,ls[y]}; ls[y]=edCnt;
}
void dfs1(int now) {
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa[now]) continue;
dep[e[i].y]=dep[now]+1; dis[e[i].y]=dis[now]+e[i].w;
fa[e[i].y]=now; dfs1(e[i].y); size[now]+=size[e[i].y];
}
}
void dfs2(int now,int up) {
int mx=0; bl[now]=up;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&size[e[i].y]>size[mx]) mx=e[i].y;
}
if (!mx) return ;
dfs2(mx,up);
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&e[i].y!=mx) dfs2(e[i].y,e[i].y);
}
}
void get_root(int now,int from) {
size[now]=1; mx[now]=0;
for (int i=ls[now];i;i=e[i].next) {
if (del[e[i].y]||e[i].y==from) continue;
get_root(e[i].y,now); size[now]+=size[e[i].y];
mx[now]=std:: max(mx[now],size[e[i].y]);
}
mx[now]=std:: max(mx[now],sum-size[now]);
if (mx[now]<mx[root]) root=now;
}
void build(int now) {
for (int i=ls[now];i;i=e[i].next) {
if (del[e[i].y]) continue;
root=0; mx[0]=INF; sum=size[e[i].y];
get_root(e[i].y,now);
acs[root]=now; del[root]=1;
build(root);
}
}
int get_lca(int x,int y) {
for (;bl[x]!=bl[y];x=fa[bl[x]]) if (dep[bl[x]]<dep[bl[y]]) std:: swap(x,y);
return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y) {
return dis[x]+dis[y]-dis[get_lca(x,y)]*2;
}
void change(int st) {
vec1[st].push_back(0);
for (int x=st;acs[x];x=acs[x]) {
int dd=get_dis(st,acs[x]);
vec1[acs[x]].push_back(dd);
vec2[x].push_back(dd);
}
}
int check(int st,int mid) {
int res=std:: upper_bound(vec1[st].begin(),vec1[st].end(),mid)-vec1[st].begin();
for (int x=st;acs[x];x=acs[x]) {
int dd=get_dis(st,acs[x]);
res+=std:: upper_bound(vec1[acs[x]].begin(),vec1[acs[x]].end(),mid-dd)-vec1[acs[x]].begin();
res-=std:: upper_bound(vec2[x].begin(),vec2[x].end(),mid-dd)-vec2[x].begin();
}
return res-1;
}
int ask(int x,int k) {
int res=0;
for (int l=1,r=INF;l<=r;) {
int mid=(l+r)>>1;
if (check(x,mid)>=k) r=mid-1,res=mid;
else l=mid+1;//,res=mid;
}
return res;
}
int main(void) {
freopen("data.in","r",stdin);
// freopen("myp.out","w",stdout);
int n=read(),m=read();
rep(i,2,n) {
int x=read(),y=read(),w=read();
add_edge(x,y,w);
}
dfs1(dep[1]=1); dfs2(1,1);
root=0; mx[0]=INF; sum=n;
get_root(1,0);
del[root]=1;
build(root);
rep(i,1,n) change(i);
rep(i,1,n) {
std:: sort(vec1[i].begin(),vec1[i].end());
std:: sort(vec2[i].begin(),vec2[i].end());
}
rep(i,1,n) printf("%d\n", ask(i,m));
printf("%d\n", INF);
return 0;
}