CF1039D You Are Given a Tree
这不是noip原题吗?然而不一样
对\(k\leq SIZE\)直接一遍dfs搜过去\(O(n)\),这部分是\(O(n\cdot SIZE)\)的
对\(k>SIZE\)可以发现答案不超过\(\frac{n}{SIZE}\),对每个答案二分右边界,这部分是\(O(\frac{n}{SIZE}\cdot n\log n)\)的
显然取\(SIZE=\sqrt{n\log n}\)最优,然后傻逼题做完了
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int fir[100010],dis[200010],nxt[200010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
std::vector<int>G[100010];
int tot,mid,d;
il int dfs(int x){
int mx=0,cmx=0;
for(int i=0;i<G[x].size();++i){
d=dfs(G[x][i]);
if(d>mx)cmx=mx,mx=d;
else if(d>cmx)cmx=d;
}
if(mx+cmx+1>=mid)++tot,mx=-1;
return mx+1;
}
il vd DFS(int x,int fa=-1){
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i])continue;
G[x].push_back(dis[i]);
DFS(dis[i],x);
}
}
int R[100010];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),a,b,blk=sqrt(n*log2(n)),lim=n/blk,l,r;
for(int i=1;i<n;++i)a=gi(),b=gi(),link(a,b),link(b,a);
DFS(1);
for(int i=1;i<=blk;++i)mid=i,tot=0,dfs(1),printf("%d\n",tot);
for(int i=0;i<=lim;++i){
l=0,r=n;
while(l<r){
mid=((l+r)>>1)+1;tot=0;dfs(1);
if(tot>=i)l=mid;
else r=mid-1;
}
R[i]=l;
}
int p=lim;
for(int i=blk+1;i<=n;++i){
while(R[p]<i)--p;
printf("%d\n",p);
}
return 0;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。