点分治序就是每次点分治时的dfs序拼起来。点分治序的长度应该是nlogn的。
然后对于每一条路径(u,v),在出现了u的分治结构中,v总是在点分治序的一段区间里,就可以同NOI2010超级钢琴一样维护了,就是从堆中取出最大值,并把所在区间再分成两部分扔进堆里,重复m次即可。复杂度O(nlog^2n)。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=50010;
const int mlgn=900010;
int n,m,tim,a[mlgn],fz[maxn],ed[maxn],sz[maxn],st[mlgn][20],lg[mlgn];
bool vis[maxn];
struct edge
{
int t,w;
edge *next;
}*con[maxn];
struct node
{
int p,l,r,w,d;
}t[mlgn];
inline bool operator <(const node &p,const node &q){return p.w<q.w;}
priority_queue <node> Q;
inline int read()
{
char ch=getchar();int x=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline int amx(int p,int q)
{
return (a[p]<a[q])?q:p;
}
void ins(int x,int y,int w)
{
edge *p=new edge;
p->t=y;
p->w=w;
p->next=con[x];
con[x]=p;
}
void getroot(int v,int fa,int size,int &root)
{
bool flag=1;
sz[v]=1;
for(edge *p=con[v];p;p=p->next)
if(!vis[p->t]&&p->t!=fa)
{
getroot(p->t,v,size,root);
sz[v]+=sz[p->t];
if(sz[p->t]*2>size) flag=0;
}
if(size>2*sz[v]) flag=0;
if(flag) root=v;
}
void dfs(int v,int fa,int d)
{
fz[v]=++tim;
a[tim]=d;
for(edge *p=con[v];p;p=p->next)
if(!vis[p->t]&&p->t!=fa) dfs(p->t,v,d+p->w);
ed[v]=tim;
}
void solve(int v,int size)
{
int rt;
getroot(v,-1,size,rt);
vis[rt]=1;
dfs(rt,-1,0);
for(edge *p=con[rt];p;p=p->next)
if(!vis[p->t])
for(int i=fz[p->t];i<=ed[p->t];i++)
t[i].p=i,t[i].l=fz[rt],t[i].r=fz[p->t]-1;
for(edge *p=con[rt];p;p=p->next)
if(!vis[p->t]) solve(p->t,(sz[p->t]>sz[rt]?size-sz[rt]:sz[p->t]));
}
void init()
{
lg[0]=-1;
for(int i=1;i<=tim;i++)
lg[i]=lg[i>>1]+1;
for(int i=1;i<=tim;i++)
st[i][0]=i;
for(int k=1;(1<<k)<=tim;k++)
for(int i=1;i<=tim;i++)
if(i+(1<<(k-1))>tim) st[i][k]=st[i][k-1];
else st[i][k]=amx(st[i+(1<<(k-1))][k-1],st[i][k-1]);
}
inline int qry(int l,int r)
{
int k=lg[r-l+1];
return amx(st[l][k],st[r-(1<<k)+1][k]);
}
int main()
{
n=read();m=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read(),w=read();
ins(x,y,w);
ins(y,x,w);
}
solve(1,n);
init();
for(int i=1;i<=tim;i++)
{
t[i].d=qry(t[i].l,t[i].r);
t[i].w=a[t[i].d]+a[t[i].p];
Q.push(t[i]);
}
while(m--)
{
node r=Q.top(),s=r,u=r;Q.pop();
printf("%d\n",r.w);
if(r.d>r.l)
{
s.r=r.d-1;
s.d=qry(s.l,s.r);
s.w=a[s.d]+a[s.p];
Q.push(s);
}
if(r.d<r.r)
{
u.l=r.d+1;
u.d=qry(u.l,u.r);
u.w=a[u.d]+a[u.p];
Q.push(u);
}
}
return 0;
}