題目鏈接:https://codeforces.com/contest/1009/problem/F
題目大意:給你一棵樹,定義d(x,i)表示x子樹內和x距離爲i的節點數,對每個x求使d(x,i)最大的i,如有多個輸出最小的。
長鏈剖分是一種類似dsu on tree的小trick,可以把維護子樹中只與深度有關的信息做到線性的時間複雜度。
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define mp make_pair
#define pb push_back
#define ll long long
using namespace std;
const int N = 1e6+1;
vector<int>nxt[N];
int son[N],len[N];
void split(int u,int f) {
son[u] = 0;
len[u] = 1;
for(auto v:nxt[u]) {
if(v==f)continue;
split(v,u);
if(len[son[u]]<len[v]) son[u] = v,len[u] = len[v]+1;
}
}
//---------------------
ll pos[N],dp[N],ans[N],cnt; //空間公用,將dp數組從二維壓成一維
void dfs(int u,int f) { //dp[u][i] 表示u這顆子樹內距離u爲i的點的個數
pos[u] = ++cnt;
dp[pos[u]] = 1; //dp[u][0] = 1;
if(son[u]) dfs(son[u],u),ans[u] = ans[son[u]]+1; //繼承重兒子的答案
for(auto v:nxt[u]) {
if(v==f||v==son[u]) continue;
dfs(v,u);
rep(j, 0, len[v]-1) {
dp[pos[u]+j+1] += dp[pos[v]+j]; //dp[u][j+1] += dp[v][j];
if(dp[pos[u]+j+1]>dp[pos[u]+ans[u]]) ans[u] = j+1;
else if(dp[pos[u]+j+1]==dp[pos[u]+ans[u]]) ans[u] = min(ans[u],1ll*j+1);
}
}
if(dp[pos[u]+ans[u]]==1) ans[u] = 0; //特判
}
int main() {
//freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int n;
cin>>n;
rep(i, 1, n-1) {
int u,v;
cin>>u>>v;
nxt[u].pb(v);
nxt[v].pb(u);
}
split(1,0);
dfs(1,0);
rep(i, 1, n) cout<<ans[i]<<endl;
return 0;
}