original: http://codeforces.com/problemset/problem/958/B2
question:
Give you a tree with n points, you choose some points, and count the number of points that in the simple path of two chosen points.
Print the maximum of number by chosen 1,2…n points.
analyze:
It’s obvious that the chosen points is leaves.
Firstly, find the two farthest points, use one point in their path as root to build the tree.
We could maintain every leave’s value, that means if you choose this leave, the addition you could get.
By give every point a dfs-index, you can deal the value of the leaves in a subtree by Segment Tree easily.
#include<bits/stdc++.h>
using namespace std;
#define F double
#define LL long long
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs ((rt<<1)|1)
const int maxn=100009;
#define pill pair<int,int>
int tr[maxn<<2];
int laz[maxn<<2];
void down(int rt,int l,int r){
if(laz[rt]){
laz[ls]+=laz[rt];
laz[rs]+=laz[rt];
tr[ls]+=laz[rt];
tr[rs]+=laz[rt];
laz[rt]=0;
}
}
void update(int rt,int l,int r,int L,int R,int v){
if(l>=L&&r<=R){
tr[rt]+=v;
laz[rt]+=v;
return;
}
down(rt,l,r);
if(L<=mid)update(ls,l,mid,L,R,v);
if(R>mid)update(rs,mid+1,r,L,R,v);
tr[rt]=max(tr[ls],tr[rs]);
}
pill query(int rt,int l,int r,int L,int R){
if(l>=L&&r<=R){
if(l==r)
return {tr[rt],l};
down(rt,l,r);
if(tr[ls]==tr[rt])
return query(ls,l,mid,L,R);
else
return query(rs,mid+1,r,L,R);
}
pill ans={-1,0};
down(rt,l,r);
if(L<=mid)ans=query(ls,l,mid,L,R);
if(R>mid)ans=max(ans,query(rs,mid+1,r,L,R));
return ans;
}
int head[maxn],to[maxn<<1],nex[maxn<<1],now;
int deg[maxn];
void add(int a,int b){
nex[++now]=head[a];head[a]=now;to[now]=b;
}
int dfsn[maxn],idn,dep[maxn],fa[maxn],siz[maxn];
int fin[maxn];
int n,rt,ll,rr;
void init(int p,int Fa,int d){
fa[p]=Fa;
dep[p]=d;
siz[p]=1;
dfsn[p]=++idn;
fin[idn]=p;
for(int i=head[p];i;i=nex[i]){
int u=to[i];
if(u==Fa)continue;
init(u,p,d+1);
siz[p]+=siz[u];
}
}
void cut(int p){//**
int now=query(1,1,n,dfsn[p],dfsn[p]).first;
update(1,1,n,dfsn[p],dfsn[p],-now);
int pre=p;
p=fa[p];
now--;
while(1){
if(now==0)break;
for(int i=head[p];i;i=nex[i]){
int u=to[i];
if(u==pre||u==fa[p])continue;
update(1,1,n,dfsn[u],dfsn[u]+siz[u]-1,-now);
}
pre=p;
p=fa[p];
now--;
}
}
int main(){
scanf("%d",&n);
if(n==1)return 0*printf("1\n");
if(n==2)return 0*printf("1 2\n");
for(int i=1;i<n;i++){
int a,b;scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
deg[a]++;deg[b]++;
}
init(1,-1,1);
int ma=-1;
for(int i=1;i<=n;i++){
if(dep[i]>ma)ma=dep[i],ll=i;
}
init(ll,-1,1);
ma=-1;
for(int i=1;i<=n;i++){
if(dep[i]>ma)ma=dep[i],rr=i;
}
rt=fa[rr];
int ans=dep[rr];
printf("%d %d ",1,dep[rr]);
//--------------------------------------------------------
idn=0;
init(rt,-1,1);
for(int i=1;i<=n;i++){
if(deg[i]==1){
update(1,1,n,dfsn[i],dfsn[i],dep[i]);
}
}
cut(ll);
cut(rr);
/*printf("\nrt ll rr: %d %d %d\n",rt,ll,rr);
for(int i=1;i<=n;i++){
printf("%d : %d\n",i,query(1,1,n,dfsn[i],dfsn[i]).first);
}*/
int ct=2;
if(ans<n)
while(1){
pill p=query(1,1,n,1,n);
ans+=p.first;
printf("%d ",ans);
ct++;
if(ans==n)break;
cut(fin[p.second]);
}
for(int i=ct+1;i<=n;i++)printf("%d%c",n,(i==n?'\n':' '));
}