题意
给定一个N个结点的树,结点用正整数1..N编号。每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路边上经过边的权值。其中要求a
分析
首先两点距离,先想到点分治
对于每个点,再对于每个分治重心,肯定可以找到分治中心中除这个点外的其它子树的最大值
然后我们建出点分树之后,跑出dfs序,然后找其它子树的最大值就是一段连续的区间
我们可以用st表维护区间最大的一个点的值,之后再把一个区间变成两个小区间,就像NOI2010的超级钢琴一样,然后就用 O(Nlog2N) O ( N l o g 2 N ) 解决了这个问题
卡卡常就可以了
代码
#include <bits/stdc++.h>
#define bin(i) (1<<(i))
using namespace std;
const int N = 50010;
char O[1<<14],*S=O,*T=O;
#define gc (S==T&&(T=(S=O)+fread(O,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
int x=0,f=1; char ch=gc;
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=gc;}
return x*f;
}
inline void write(int x)
{
int num=0; char ch[15];
while(x) ch[++num]=x%10+'0',x/=10;
while(num) putchar(ch[num--]);
putchar('\n');
}
inline void _max(int &x,int y){x=x>y ? x : y;}
struct node{int x,y,next,d;}edge[N<<1],e[N]; int len,first[N],l;
void ins(int x,int y,int d){len++; edge[len].x=x; edge[len].y=y; edge[len].d=d; edge[len].next=first[x]; first[x]=len;}
bool bo[N]; int mxx = 0,p;
int siz[N];
inline void dfs2(int x,int f)
{
siz[x] = 1;
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y; if(y==f || bo[y]) continue;
dfs2(y,x); siz[x] += siz[y];
}
}
inline void find_root(int x,int f,int tot)
{
int maxx = 0;
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
if(y==f || bo[y]) continue;
_max(maxx,siz[y]); find_root(y,x,tot);
}
_max(maxx , tot - siz[x]);
if(maxx < mxx)
{
mxx = maxx , p = x;
}
}
int D[N][16];
inline void dfs3(int x,int f,int deep)
{
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
if(bo[y] || y==f) continue;
D[y][deep] = D[x][deep] + edge[k].d; dfs3(y,x,deep);
}
}
inline int dfs1(int x,int f,int deep)
{
dfs2(x,0); mxx = INT_MAX; p=0; find_root(x,0,siz[x]); x=p;
D[x][deep] = 0; dfs3(x,0,deep);
bo[x] = 1; for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
if(y==f || bo[y]) continue;
l++; e[l].x=x; e[l].y=dfs1(y,x,deep+1);
}return x;
}
int s[N],d[N],h[N]; int id = 0; int fa[N],dep[N] , mx[16][N][16];
inline void dfs4(int x,int f)
{
s[x] = ++id; h[id] = x; fa[x] = f;
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y = edge[k].y;
dep[y] = dep[x] + 1; dfs4(y,x);
}d[x] = id;
}
struct node1
{
int x,y,d,l,r,ret; // dfn parent dep right
node1(){}
node1(int _x,int _y,int _d,int _l,int _r,int _ret){x=_x; y=_y; d=_d; l=_l; r=_r; ret = _ret;}
};
bool operator <(const node1 &x,const node1 &y) {return x.ret < y.ret;}
priority_queue<node1>q;
int lg2[N];
inline int find(int L,int R,int i)
{
int dd = lg2[R-L+1];
int x = h[mx[i][L][dd]]; int y = h[mx[i][R-bin(dd)+1][dd]];
return (D[x][i] >= D[y][i]) ? s[x] : s[y];
}
inline int calc(node1 x){return D[h[x.x]][x.d] + D[h[x.y]][x.d];}
int main()
{
int n = read(); int k = read(); memset(first,-1,sizeof(first)); len = 0;
for(int i=1;i<n;i++)
{
int a = read(); int b = read(); int c = read();
ins(a,b,c); ins(b,a,c);
}
for(int i=2;i<=n;i++) lg2[i] = lg2[i>>1] + 1;
memset(bo,0,sizeof(bo));
l=0; int rt = dfs1(1,0,0);
len = 0; memset(first,-1,sizeof(first));
for(int i=1;i<=l;i++) ins(e[i].x,e[i].y,0);
dfs4(rt,0);
for(int i=0;i<=15;i++)
{
for(int j=1;j<=n;j++) mx[i][s[j]][0] = s[j];
for(int j=1;j<=15;j++) for(int kk=1;kk<=n;kk++) if(kk+(1<<j)-1<=n)
{
int x,y; x = h[mx[i][kk][j-1]]; y = h[mx[i][kk+(1<<(j-1))][j-1]];
mx[i][kk][j] = (D[x][i] >= D[y][i]) ? s[x] : s[y];
}
}
for(int i=1;i<=n;i++)
{
int x = fa[i]; int lst = i;
while(x)
{
int L = d[lst]+1; int R = d[x];
if(L<=R)
{
node1 xx = node1(s[i],find(L,R,dep[x]),dep[x],L,R,0);
int c = calc(xx); xx.ret=c; q.push(xx);
}
lst = x; x = fa[x];
}
if(s[i]<d[i])
{
node1 xx = node1(s[i],find(s[i]+1,d[i],dep[i]),dep[i],s[i]+1,d[i],0);
int c = calc(xx); xx.ret=c;
q.push(xx);
}
}
while(k--)
{
node1 x = q.top(); q.pop();
write(calc(x));
int L = x.l; int R = x.y-1; node1 xx = node1(x.x,find(L,R,x.d),x.d,L,R,0);
int c = calc(xx); xx.ret=c;
if(L<=R) q.push(xx);
L = x.y+1; R = x.r; xx = node1(x.x,find(L,R,x.d),x.d,L,R,0);
c = calc(xx); xx.ret=c;
if(L<=R) q.push(xx);
}
return 0;
}