题意
传送门 Codeforces 1009F Dominant Indices
题解
维护以 x x x 为根的子树中深度为 d d d 的节点数量 c n t [ d ] cnt[d] cnt[d],那么 x x x 对应的答案即最大的 c n t [ d ] cnt[d] cnt[d] 中最小的 d d d 减去 d e p [ x ] dep[x] dep[x]。使用 s t d : : s e t std::set std::set 维护以 c n t [ d ] cnt[d] cnt[d] 为第一关键字降序排序, d d d 为第二关键字升序排序的子树信息二元组 ( c n t [ d ] , d ) (cnt[d],d) (cnt[d],d)。
使用 d s u o n t r e e dsu\ on\ tree dsu on tree 统计子树信息,总时间复杂度 O ( N log 2 N ) O(N\log^2N) O(Nlog2N)。直接递归统计子树信息可能会超时,那么使用树的 D F S DFS DFS 序迭代统计进行优化。
#include <bits/stdc++.h>
using namespace std;
struct node
{
int n, d;
bool operator<(const node &o) const { return n != o.n ? n > o.n : d < o.d; }
};
const int maxn = 1000005;
int N, sz[maxn], dep[maxn];
int clk, vs[maxn], L[maxn], R[maxn];
int tot, head[maxn], to[maxn << 1], nxt[maxn << 1];
int cnt[maxn], res[maxn];
bool hv[maxn];
set<node> st;
void add_edge(int x, int y) { to[tot] = y, nxt[tot] = head[x], head[x] = tot++; }
void pdfs(int x, int f, int d)
{
vs[clk] = x, L[x] = clk++;
dep[x] = d, sz[x] = 1;
for (int i = head[x], y; ~i; i = nxt[i])
if ((y = to[i]) != f)
pdfs(y, x, d + 1), sz[x] += sz[y];
R[x] = clk;
}
void add(int x, int f)
{
int d = dep[x];
if (cnt[d])
st.erase(node{cnt[d], d});
st.insert(node{++cnt[d], d});
for (int i = head[x], y; ~i; i = nxt[i])
if ((y = to[i]) != f && !hv[y])
for (int j = L[y]; j < R[y]; ++j)
{
d = dep[vs[j]];
if (cnt[d])
st.erase(node{cnt[d], d});
st.insert(node{++cnt[d], d});
}
}
void del(int x, int f)
{
for (int i = L[x]; i < R[x]; ++i)
cnt[dep[vs[i]]] = 0;
st.clear();
}
void dfs(int x, int f, int keep)
{
int mx = -1, hs = -1;
for (int i = head[x], y; ~i; i = nxt[i])
if ((y = to[i]) != f && sz[y] > mx)
mx = sz[y], hs = y;
for (int i = head[x], y; ~i; i = nxt[i])
if ((y = to[i]) != f && y != hs)
dfs(y, x, 0);
if (hs != -1)
dfs(hs, x, 1), hv[hs] = 1;
add(x, f);
res[x] = st.begin()->d - dep[x];
if (hs != -1)
hv[hs] = 0;
if (!keep)
del(x, f);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N;
memset(head, -1, sizeof(int) * N);
for (int i = 1, x, y; i < N; ++i)
{
cin >> x >> y;
--x, --y;
add_edge(x, y), add_edge(y, x);
}
pdfs(0, -1, 0);
dfs(0, -1, 1);
for (int i = 0; i < N; ++i)
cout << res[i] << '\n';
return 0;
}