# include <iostream>
# include <vector>
using namespace std;
template<class T> void chmax(T& x, const T& y) {x=max(x,y);}
const int MAX=2e5+11,INF=1e9,LOG=20;
int n;
vector<int> adj[MAX];
int out[MAX];
int SZ[MAX];
int H[MAX];
int st[MAX][LOG];
void dfs_lca(int curr, int par)
{
SZ[curr]=1;
for(int nxt: adj[curr])
{
if(nxt==par) continue;
H[nxt]=H[curr]+1;
st[nxt][0]=curr;
dfs_lca(nxt,curr);
SZ[curr]+=SZ[nxt];
}
}
void lca_precalc()
{
dfs_lca(1,0);
for(int j=1;j<LOG;j++)
{
for(int i=1;i<=n;i++)
{
if(H[i]-(1<<j)<0) continue;
st[i][j]=st[st[i][j-1]][j-1];
}
}
}
int lift(int u, int k)
{
for(int j=LOG-1;j>=0;j--)
{
if(k-(1<<j)>=0)
{
u=st[u][j];
k-=(1<<j);
}
}
return u;
}
int get_lca(int u, int v)
{
if(H[u]<H[v]) swap(u,v);
for(int j=LOG-1;j>=0;j--)
{
if(H[u]-(1<<j)>=H[v])
{
u=st[u][j];
}
}
if(u==v) return u;
for(int j=LOG-1;j>=0;j--)
{
if(H[u]-(1<<j)>=0 and st[u][j]!=st[v][j])
{
u=st[u][j];
v=st[v][j];
}
}
return st[u][v];
}
pair<int,int> sizes(int u, int v)
{
int lca=get_lca(u,v);
if(lca!=u and lca!=v) return {SZ[u],SZ[v]};
bool Swap=0;
if(u!=lca)
{
Swap=1;
swap(u,v);
}
pair<int,int> ans;
ans={n-SZ[lift(v,H[v]-H[u]-1)],SZ[v]};
if(Swap) swap(ans.first,ans.second);
return ans;
}
bool banned[MAX];
int sz[MAX];
int h[MAX];
void dfs_sz(int curr, int par)
{
sz[curr]=1;
for(int nxt: adj[curr])
{
if(nxt==par or banned[nxt]) continue;
h[nxt]=h[curr]+1;
dfs_sz(nxt,curr);
sz[curr]+=sz[nxt];
}
}
int get_centroid(int curr, int par, int N)
{
for(int nxt: adj[curr])
{
if(nxt==par or banned[nxt]) continue;
if(sz[nxt]*2>N) return get_centroid(nxt,curr,N);
}
return curr;
}
struct segtree
{
int tree[MAX*4];
void build(int v=1, int l=0, int r=n)
{
if(l==r)
{
tree[v]=-INF;
return ;
}
int mid=(l+r)/2;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
tree[v]=max(tree[v*2],tree[v*2+1]);
}
void update(int pos, int d, int v=1, int l=0, int r=n)
{
if(l==r)
{
if(d==-INF) tree[v]=d;
else tree[v]=max(tree[v],d);
return ;
}
int mid=(l+r)/2;
if(pos<=mid) update(pos,d,v*2,l,mid);
else update(pos,d,v*2+1,mid+1,r);
tree[v]=max(tree[v*2],tree[v*2+1]);
}
int query(int le, int ri, int v=1, int l=0, int r=n)
{
if(ri<l or r<le) return -INF;
if(le<=l and r<=ri) return tree[v];
int mid=(l+r)/2;
return max(query(le,ri,v*2,l,mid),query(le,ri,v*2+1,mid+1,r));
}
}tree;
int cen;
void dfs1(int curr, int par)
{
int sz1,sz2;
tie(sz1,sz2)=sizes(curr,cen);
chmax(out[min(sz1,sz2)*2],h[curr]);
chmax(out[sz1*2],h[curr]+tree.query(sz1,n));
for(int nxt: adj[curr])
{
if(nxt==par or banned[nxt]) continue;
dfs1(nxt,curr);
}
}
vector<int> rollback;
void dfs2(int curr, int par)
{
int sz1=sizes(curr,cen).first;
tree.update(sz1,h[curr]);
rollback.push_back(sz1);
for(int nxt: adj[curr])
{
if(nxt==par or banned[nxt]) continue;
dfs2(nxt,curr);
}
}
void cd(int curr)
{
dfs_sz(curr,0);
curr=get_centroid(curr,0,sz[curr]);
cen=curr;
h[curr]=0;
dfs_sz(curr,0);
//cout<<"->"<<curr<<"\n";
//for(int i=1;i<=n;i++) cout<<i<<":"<<h[i]<<" "<<from[i]<<"\n";
for(int nxt: adj[curr])
{
if(banned[nxt]) continue;
dfs1(nxt,curr);
dfs2(nxt,curr);
}
for(int x: rollback) tree.update(x,-INF);
rollback.clear();
banned[curr]=1;
for(int nxt: adj[curr])
{
if(banned[nxt]) continue;
cd(nxt);
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
lca_precalc();
tree.build();
cd(1);
int start=n;
if(start%2==1) start--;
for(int i=start-2;i>=2;i--) out[i]=max(out[i],out[i+2]);
for(int i=1;i<=n;i++) out[i]++;
for(int i=1;i<=n;i++) cout<<out[i]<<"\n";
return 0;
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |