如果 $k$ 值确定的话,我们直接来一个 $O(n)$ 的贪心就行.
那么我们就将 $k$ 分为大于 $B$ 和小于 $B$ 两部分处理.
对于小于 $B$ 的部分,暴力处理,复杂度为 $O(nB)$.
对于大于 $B$ 的部分,取值分别为 $[0,\frac{n}{B}]$ 且依次递减.
那么我们就可以二分每种取值的区间.
由于有 $\frac{n}{B}$ 种取值,计算每个取值区间为 $O(n \log n)$,故这部分复杂度为 $\frac{n}{B} n \log n$
一般来说,这个 $B$ 取 200 左右是比较优的.
code:
#include <bits/stdc++.h>
#define B 203
#define N 100006
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,edges,tim;
int hd[N],to[N<<1],nex[N<<1],f[N],vis[N],maxx[N],po[N],fa[N];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs(int x,int ff)
{
po[++tim]=x,fa[x]=ff;
for(int i=hd[x];i;i=nex[i])
if(to[i]!=ff)
dfs(to[i],x);
}
int solve(int x)
{
f[x]=0;
int i,j;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;++i) maxx[i]=1;
for(i=tim;i>=1;--i)
{
int u=po[i];
if(fa[u]&&!vis[u])
{
if(vis[fa[u]]==0)
{
if(maxx[fa[u]]+maxx[u]>=x)
++f[x],maxx[fa[u]]=0,vis[fa[u]]=1;
else
maxx[fa[u]]=max(maxx[fa[u]],maxx[u]+1);
}
}
}
return f[x];
}
void init(int M)
{
int i,j;
f[1]=n;
for(i=2;i<=M;++i)
solve(i);
}
int main()
{
// setIO("input");
int i,j;
scanf("%d",&n);
for(i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs(1,0);
init(min(n,B));
if(n<=B)
{
for(i=1;i<=n;++i)
printf("%d\n",f[i]);
}
else
{
int An;
for(i=B+1;i<=n;i=An+1)
{
An=i;
int l=i,r=n;
int tmp=solve(l);
while(l<=r)
{
int mid=(l+r)>>1;
if(solve(mid)==tmp)
An=mid,l=mid+1;
else
r=mid-1;
}
for(j=i;j<=An;++j)
f[j]=tmp;
}
for(i=1;i<=n;++i)
printf("%d\n",f[i]);
}
return 0;
}