Problem:
珍しい都市(Unique Cities)
JOI 国には$N$ 個の都市があり，1 から$N$ までの番号がついている．これらの都市は$N - 1$ 本の道路で結ばれている．$i$ 番目($1 \leq i \leq N - 1$) の道路は都市$A_i$ と都市$B_i$ を結んでおり，双方向に通行可能である．どの都市からどの都市へも何本かの道路を通行することで移動できる．
JOI 国にはいくつかの特産品が存在する．特産品には，種類を表す1 以上$M$ 以下の番号が付けられている(JOI 国で生産されている特産品に対応していない番号があるかもしれない)．各都市は1 つの特産品を生産しており，都市$j$ ($1 \leq j \leq N$) では特産品$C_j$ を生産している．複数の都市が同じ種類の特産品を生産することがあるかもしれない．
2 つの都市の間の距離は，その間を移動するために通る道路の本数の最小値である．都市$x$ ($1 \leq x \leq N$)から見て都市$y$ ($1 \leq y \leq N, y \ne x$) が珍しい都市であるとは，すべての都市$z$ ($1 \leq z \leq N, z \ne x, z \ne y) について，都市$x, y$ 間の距離と都市$x, z$ 間の距離が異なることを意味する．
JOI 国の大臣であるK 理事長は，すべての$j$ ($1 \leq j \leq N$) について，都市$j$ から見て珍しい都市で生産されている特産品が何種類あるかを知りたい．
JOI 国の道路の情報と，各都市で生産されている特産品の番号が与えられたとき，各都市ごとに，その都市から見て珍しい都市で生産されている特産品が何種類あるかを求めるプログラムを作成せよ．
入力
入力は以下の形式で標準入力から与えられる．
$N$ $M$
$A_1$ $B_1$
:
$A_{N-1}$ $B_{N-1}$
$C_1$ ... $C_N$
出力
標準出力に$N$ 行で出力せよ． $j$ 行目($1 \leq j \leq N$) には，都市$j$ から見て珍しい都市で生産されている特産品が何種類あるかを出力せよ．
制約
$ 2 \leq N \leq 200 000$．
$ 1 \leq M \leq N$．
$ 1 \leq A_i \leq N (1 \leq i \leq N - 1)，1 \leq B_i \leq N (1 \leq i \leq N - 1)$．
$ A_i \ne B_i (1 \leq i \leq N - 1)$．
どの都市からどの都市へも何本かの道路を通行することで移動できる．
$ 1 \leq C_j \leq M (1 \leq j \leq N)$．
入出力例
入力例1
5 4
1 2
2 3
3 4
3 5
1 2 1 2 4
出力例1
2
0
1
1
1
都市1 から見て珍しい都市は都市2; 3 であり，そこで生産される特産品は特産品2; 1 なので，答えは2種類である．
都市2 から見て珍しい都市は存在しないので，答えは0 種類である．
都市3 から見て珍しい都市は都市1 であり，そこで生産される特産品は特産品1 なので，答えは1 種類である．
都市4 から見て珍しい都市は都市1; 3 であり，どちらの都市においても生産される特産品は特産品1 なので，答えは1 種類である．
都市5 から見て珍しい都市は都市1; 3 であり，どちらの都市においても生産される特産品は特産品1 なので，答えは1 種類である．
番号3 の特産品は存在しないことに注意せよ．
入力例2
7 1
1 2
2 3
3 4
4 5
5 6
6 7
1 1 1 1 1 1 1
出力例2
1
1
1
0
1
1
1
入力例3
10 10
2 6
5 8
10 8
1 4
10 6
4 5
10 7
6 9
3 7
1 2 3 4 5 6 7 8 9 10
出力例3
4
3
4
2
0
2
2
0
3
2
入力例4
22 12
9 6
12 13
4 20
21 22
3 19
2 9
6 18
18 11
18 3
16 2
6 4
3 17
16 10
8 16
22 1
16 14
15 8
9 21
2 12
21 5
12 7
1 1 4 8 4 11 7 6 7 11 6 11 10 4 7 5 3 12 9 6 12 2
出力例4
2
0
1
1
1
1
1
0
0
1
2
0
1
1
2
0
2
1
2
3
0
0
情報オリンピック日本委員会作 『第18 回日本情報オリンピック(JOI 2018/2019) 本選』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
static const int MAXN = 200000;

int N, M;
vi G[MAXN+1];
int C[MAXN+1], ans[MAXN+1], cnt[MAXN+1];
int dep[MAXN+1], son[MAXN+1], mx1[MAXN+1], mx2[MAXN+1];
int stk[MAXN+1];

int rt = 0, tp = 0, sumv = 0;

// 1) DFS で最遠点を探す
void dfs_far(int u, int p){
    dep[u] = dep[p] + 1;
    if(dep[u] > dep[rt]) rt = u;
    for(int v : G[u]){
        if(v == p) continue;
        dfs_far(v, u);
    }
}

// 2) 各ノードの heavy-child, mx1, mx2 を計算
void dfs1(int u, int p){
    dep[u] = dep[p] + 1;
    mx1[u] = mx2[u] = son[u] = 0;
    for(int v : G[u]){
        if(v == p) continue;
        dfs1(v, u);
        int d = mx1[v] + 1;
        if(d > mx1[u]){
            mx2[u] = mx1[u];
            mx1[u] = d;
            son[u] = v;
        } else if(d > mx2[u]){
            mx2[u] = d;
        }
    }
}

// スタックに色を追加／削除
inline void add(int x){
    if(cnt[C[x]]++ == 0) ++sumv;
}
inline void remove_(int x){
    if(--cnt[C[x]] == 0) --sumv;
}

// 3) Heavy–Light 風に DFS して ans を更新
void dfs2(int u, int p){
    if(p){
        stk[++tp] = p;
        add(p);
    }
    if(son[u]){
        int limit = dep[u] - mx2[u];
        while(tp && dep[stk[tp]] >= limit){
            remove_(stk[tp--]);
        }
        dfs2(son[u], u);
    }
    int limit = dep[u] - mx1[u];
    while(tp && dep[stk[tp]] >= limit){
        remove_(stk[tp--]);
    }
    for(int v : G[u]){
        if(v == p || v == son[u]) continue;
        dfs2(v, u);
    }
    ans[u] = max(ans[u], sumv);
    if(p && tp && stk[tp] == p){
        remove_(p);
        --tp;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N >> M;
    for(int i = 1; i < N; ++i){
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i = 1; i <= N; ++i){
        cin >> C[i];
    }

    // 直径の両端を根にして2回走らせる
    dfs_far(1, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);

    int other = rt;
    rt = 0;
    dfs_far(other, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);

    for(int i = 1; i <= N; ++i){
        cout << ans[i] << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 33308
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int in() {   // 非負整数の入力
    int n = 0; int c = gc();
    do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
    return n;
}

void out(int n) { // 非負整数の表示（出力）
    char b[30];
    if (!n) pc('0');
    else {
        int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
        while (i--) pc(b[i]);
    }
    pc('\n');
}

static inline void chmax(int *a, int b) { if (*a < b) *a = b; }
#define M 200005
vector<int> g[M];
int n, m, x, y, rt, tp, sum;
int c[M], ans[M], cnt[M], dep[M], son[M], stk[M], mx1[M], mx2[M];

void get(int x, int par) {
    dep[x] = dep[par] + 1;
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v != par) get(v, x);
    }
    if (dep[x] > dep[rt]) rt = x;
}

void dfs1(int x, int par) {
    mx1[x] = mx2[x] = son[x] = 0;
    dep[x] = dep[par] + 1;
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v == par) continue;
        dfs1(v, x);
        if (mx1[v] + 1 > mx1[x]) {
            mx2[x] = mx1[x];
            son[x] = v;
            mx1[x] = mx1[v] + 1;
        } else if (mx1[v] + 1 > mx2[x]) {
            mx2[x] = mx1[v] + 1;
        }
    }
}

void add(int x) { sum += !cnt[c[x]]++; }
void del(int x) { sum -= !--cnt[c[x]]; }
void update(int x, int len) {
    while (tp && dep[x] - dep[stk[tp]] <= len) del(stk[tp--]);
}

void dfs2(int x, int par) {
    if (par) stk[++tp] = par, add(par);
    if (son[x]) {
        update(x, mx2[x]);
        dfs2(son[x], x);
    }
    update(x, mx1[x]);
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v != par && v != son[x]) dfs2(v, x);
    }
    chmax(&ans[x], sum);
    if (tp && stk[tp] == par) del(par), tp--;
}

int main() {
    n = in();
    m = in();
    for (int i = 1; i < n; ++i) {
        x = in();
        y = in();
        g[x].emplace_back(y);
        g[y].emplace_back(x);
    }
    for (int i = 1; i <= n; ++i) c[i] = in();
    get(1, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    x = rt;
    rt = 0;
    get(x, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    for (int i = 1; i <= n; ++i) out(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 33056
final_rank: 4

code_snippet: // AOJ 662 Unique Cities
// 2024.1.17

#include<bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int in() {   // 非負整数の入力
    int n = 0; int c = gc();
    do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
    return n;
}

void out(int n) { // 非負整数の表示（出力）
    char b[30];
    if (!n) pc('0');
    else {
        int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
        while (i--) pc(b[i]);
    }
    pc('\n');
}

static inline void chmax(int *a, int b) { if (*a < b) *a = b; }
#define M 200005
vector <int> g[M];
int n, m, x, y, rt, tp, sum;
int c[M], ans[M], cnt[M], dep[M], son[M], stk[M], mx1[M], mx2[M];

void get(int x, int par) {
    dep[x] = dep[par] + 1;
    for (auto v: g[x]) if (v != par) get(v, x);
    if (dep[x] > dep[rt]) rt = x;
}

void dfs1(int x, int par) {
    mx1[x] = mx2[x] = son[x] = 0;
    dep[x] = dep[par] + 1;
    for (auto v: g[x]) {
        if (v == par) continue;
        dfs1(v, x);
        if (mx1[v] + 1 > mx1[x]) mx2[x] = mx1[x], son[x] = v, mx1[x] = mx1[v] + 1;
        else if (mx1[v]+1 > mx2[x]) mx2[x] = mx1[v] + 1;
    }
}

void add(int x) { sum += !cnt[c[x]]++; }
void del(int x) { sum -= !--cnt[c[x]]; }
void update(int x, int len) {
    while (tp && dep[x]-dep[stk[tp]] <= len) del(stk[tp--]);
}

void dfs2(int x, int par){
    if (par) stk[++tp] = par, add(par);
    if (son[x]) {
        update(x, mx2[x]);
        dfs2(son[x], x);
    }
    update(x, mx1[x]);
    for (auto v: g[x]) if (v != par && v!=son[x]) dfs2(v, x);
    chmax(&ans[x], sum);
    if (tp && stk[tp] == par) del(par), tp--;
}

int main() {
    int i;
    n = in(), m = in();
    for (i = 1; i < n; ++i) {
        x = in(), y = in();
        g[x].emplace_back(y);
        g[y].emplace_back(x);
    }
    for (i = 1; i <= n; ++i) c[i] = in();
    get(1, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    x = rt, rt = 0;
    get(x, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    for (i = 1; i <= n; ++i) out(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 33124
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int in() {   // 非負整数の入力
    int n = 0; int c = gc();
    do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
    return n;
}

void out(int n) { // 非負整数の表示（出力）
    char b[30];
    if (!n) pc('0');
    else {
        int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
        while (i--) pc(b[i]);
    }
    pc('\n');
}

static inline void chmax(int *a, int b) { if (*a < b) *a = b; }
#define M 200005
vector<int> g[M];
int n, m, x, y, rt, tp, sum;
int c[M], ans[M], cnt[M], dep[M], son[M], stk[M], mx1[M], mx2[M];

void get(int x, int par) {
    dep[x] = dep[par] + 1;
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v != par) get(v, x);
    }
    if (dep[x] > dep[rt]) rt = x;
}

void dfs1(int x, int par) {
    mx1[x] = mx2[x] = son[x] = 0;
    dep[x] = dep[par] + 1;
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v == par) continue;
        dfs1(v, x);
        if (mx1[v] + 1 > mx1[x]) {
            mx2[x] = mx1[x];
            son[x] = v;
            mx1[x] = mx1[v] + 1;
        } else if (mx1[v] + 1 > mx2[x]) {
            mx2[x] = mx1[v] + 1;
        }
    }
}

void add(int x) { sum += !cnt[c[x]]++; }
void del(int x) { sum -= !--cnt[c[x]]; }
void update(int x, int len) {
    while (tp && dep[x] - dep[stk[tp]] <= len) del(stk[tp--]);
}

void dfs2(int x, int par) {
    if (par) stk[++tp] = par, add(par);
    if (son[x]) {
        update(x, mx2[x]);
        dfs2(son[x], x);
    }
    update(x, mx1[x]);
    for (size_t i = 0; i < g[x].size(); ++i) {
        int v = g[x][i];
        if (v != par && v != son[x]) dfs2(v, x);
    }
    chmax(&ans[x], sum);
    if (tp && stk[tp] == par) del(par), tp--;
}

int main() {
    n = in();
    m = in();
    for (int i = 1; i < n; ++i) {
        x = in();
        y = in();
        g[x].emplace_back(y);
        g[y].emplace_back(x);
    }
    for (int i = 1; i <= n; ++i) c[i] = in();
    get(1, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    x = rt;
    rt = 0;
    get(x, 0);
    dfs1(rt, 0);
    dfs2(rt, 0);
    for (int i = 1; i <= n; ++i) out(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 33040
final_rank: 1

code_snippet: #include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
const int NR = 200010;

int n, m;
int tot = 0;
int a[NR], cnt[NR];
int rt1 = 0, rt2 = 0;
int dep[NR], lson[NR], mx1[NR], mx2[NR];
int ans[NR];
vector<int> g[NR];
stack<int> st;

void mod(int x, int dt) {
  if (cnt[x]) tot--;
  cnt[x] += dt;
  if (cnt[x]) tot++;
}

void getD(int now, int fou) {
  dep[now] = dep[fou] + 1;
  for (int t: g[now]) {
    if (t == fou) continue;
    getD(t, now);
  }
}

void dfs1(int now, int fou) {
  dep[now] = dep[fou] + 1;
  lson[now] = mx1[now] = mx2[now] = 0;
  for (int t: g[now]) {
    if (t == fou) continue;
    dfs1(t, now);
    int tmp = mx1[t] + 1;
    if (tmp > mx1[now]) swap(mx1[now], tmp), lson[now] = t;
    if (tmp > mx2[now]) swap(mx2[now], tmp);
  }
}

void dfs2(int now, int fou) {
  if (fou) st.push(fou), mod(a[fou], 1);
  if (mx2[now])
    while (!st.empty() && dep[now] - dep[st.top()] <= mx2[now])
      mod(a[st.top()], -1), st.pop();
  if (lson[now])
    dfs2(lson[now], now);
  while (!st.empty() && dep[now] - dep[st.top()] <= mx1[now])
    mod(a[st.top()], -1), st.pop();
  ans[now] = max(ans[now], tot);
  for (int t: g[now]) {
    if (t == fou || t == lson[now]) continue;
    dfs2(t, now);	
  }
  if (!st.empty() && fou && st.top() == fou) mod(a[st.top()], -1), st.pop();
}

int main() {
  cin >> n >> m;
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v), g[v].push_back(u);
  }
  for (int i = 1; i <= n; i++) cin >> a[i];
  getD(1, 0);
  rt1 = max_element(dep + 1, dep + n + 1) - dep;
  getD(rt1, 0);
  rt2 = max_element(dep + 1, dep + n + 1) - dep;
  dfs1(rt1, 0), dfs2(rt1, 0);
  dfs1(rt2, 0), dfs2(rt2, 0);
  for (int i = 1; i <= n; i++) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 210
memory_kb: 32816
final_rank: 5

code_snippet: #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <random>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <vector>
#include <chrono>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template <class T>
istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}

template <class T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    if (!v.empty()) {
        os << v.front();
        for (int i = 1; i < v.size(); ++i) os << ' ' << v[i];
    }
    return os;
}

const int N = 200010;

int n;
int c[N], dis[N], prt[N];
pair<int, int> dep[N];
int cnt[N], seq[N], tag[N];
bool vis[N];
vector<int> g[N];

int cans;

void dfs(int u) {
    vis[u] = true;
    for (int v : g[u])
        if (!vis[v]) {
            dis[v] = dis[u] + 1;
            dfs(v);
        }
}

void addc(int x) {
    if (x == 0)
        return;
    if (!cnt[x]++)
        ++cans;
}

void ersc(int x) {
    if (x == 0)
        return;
    if (!--cnt[x])
        --cans;
}

void ins(int k, int x) {
    seq[k] = x;
    if (!tag[k])
        addc(x);
}

void ers(int k) {
    if (!tag[k])
        ersc(seq[k]);
    seq[k] = 0;
}

void add(int l, int r) {
    l = max(l, 0);
    for (int i = l; i <= r; ++i)
        if (!tag[i]++)
            ersc(seq[i]);
}

void sub(int l, int r) {
    l = max(l, 0);
    for (int i = l; i <= r; ++i)
        if (!--tag[i])
            addc(seq[i]);
}

struct DepthDecomposition {
    int dis[N], ans[N];

    void dfs2(int u) {
        dep[u] = make_pair(0, u);
        vis[u] = true;
        for (int v : g[u])
            if (!vis[v]) {
                dis[v] = dis[u] + 1;
                prt[v] = u;
                dfs2(v);
                dep[u] = max(dep[u], make_pair(dep[v].first + 1, dep[v].second));
            }
    }

    void dfs3(int u) {
        vector<int> chain;
        for (int v = dep[u].second; v != prt[u]; v = prt[v]) chain.push_back(v);
        reverse(chain.begin(), chain.end());
        add(dis[u] - dep[u].first - 2, dis[u] - 1);
        for (int v : chain) {
            sub(dis[v] - dep[v].first - 2, dis[v] - dep[v].first - 1);

            ans[v] = cans;
            ins(dis[v], c[v]);
            for (int w : g[v])
                if (prt[w] == v && dep[w].second != dep[v].second)
                    dfs3(w);
            for (int w : g[v])
                if (prt[w] == v && dep[w].second != dep[v].second)
                    add(dis[v] - dep[w].first - 1, dis[v] - 1);
            add(dis[v], dis[v]);
        }
        sub(dis[u] + dep[u].first, dis[u] + dep[u].first);
        for (int v : chain) {
            for (int w : g[v])
                if (prt[w] == v && dep[w].second != dep[v].second)
                    sub(dis[v] - dep[w].first - 1, dis[v] - 1);
            ers(dis[v]);
        }
    }

    void run(int s) {
        memset(vis, 0, sizeof(vis));
        prt[s] = 0;
        dfs2(s);
        dfs3(s);
    }

} decompS, decompT;

int main() {
#ifdef LBT
    freopen("test.in", "r", stdin);
    int nol_cl = clock();
#endif

    int m;
    scanf("%d%d", &n, &m);
    for (int rep = 1; rep < n; ++rep) {
        int u, v;
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for (int i = 1; i <= n; ++i) cin >> c[i];
    dfs(1);
    int s = max_element(dis + 1, dis + n + 1) - dis;
    memset(vis, 0, sizeof(vis));
    dfs(s);
    int t = max_element(dis + 1, dis + n + 1) - dis;
    decompS.run(s);
    decompT.run(t);
    for (int i = 1; i <= n; ++i)
        printf("%d\n", (decompS.dis[i] > decompT.dis[i] ? decompS.ans[i] : decompT.ans[i]));

#ifdef LBT
    LOG("Time: %dms\n", int((clock() - nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 32864
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <cassert>
#include <algorithm>
using namespace std;
#pragma warning (disable: 4996)

// 入力部
int N, A[1 << 19], B[1 << 19], C[1 << 19];
int M;
vector<int> X[1 << 19];

// 中心を求めるのに使うやつ
int dist[1 << 19];
int dist1[1 << 19], dist2[1 << 19];
bool iscentroid[1 << 19];

// 中心を外したグラフに関連する変数
int verdist[1 << 19];
int maxdist[1 << 19], label[1 << 19];
vector<int> Y[1 << 19];

void getdist(int pos) {
	for (int i = 1; i <= N; i++) dist[i] = (1 << 30);
	queue<int> Q; dist[pos] = 0; Q.push(pos);
	while (!Q.empty()) {
		int from = Q.front(); Q.pop();
		for (int i : X[from]) {
			if (dist[i] > dist[from] + 1) {
				dist[i] = dist[from] + 1;
				Q.push(i);
			}
		}
	}
}

vector<int> calc() {
	getdist(1);
	pair<int, int> maxn1 = make_pair(-(1 << 30), -1);
	for (int i = 1; i <= N; i++) maxn1 = max(maxn1, make_pair(dist[i], i));

	getdist(maxn1.second);
	pair<int, int> maxn2 = make_pair(-(1 << 30), -1);
	for (int i = 1; i <= N; i++) maxn2 = max(maxn2, make_pair(dist[i], i));
	for (int i = 1; i <= N; i++) dist1[i] = dist[i];

	getdist(maxn2.second);
	for (int i = 1; i <= N; i++) dist2[i] = dist[i];

	vector<pair<int, int>> V;
	for (int i = 1; i <= N; i++) {
		if (dist1[i] + dist2[i] == dist1[maxn2.second]) V.push_back(make_pair(max(dist1[i], dist2[i]), i));
	}
	sort(V.begin(), V.end());

	if (V[0].first == V[1].first) return vector<int>{ V[0].second, V[1].second };
	return vector<int>{ V[1].second, V[0].second, V[2].second };
}

void dfs1(int pos, int num) {
	maxdist[pos] = 0; label[pos] = num;
	for (int i : X[pos]) {
		if (maxdist[i] >= 0 || iscentroid[i] == true) continue;
		verdist[i] = verdist[pos] + 1;
		dfs1(i, num);
		Y[pos].push_back(i);
		maxdist[pos] = max(maxdist[pos], maxdist[i] + 1);
	}
}

// ここからはライブラリ
class BIT {
public:
	int size_ = 1;
	vector<int> bit;

	void init(int sz) {
		size_ = sz + 2;
		bit.resize(size_ + 2, 0);
		for (int i = 0; i < bit.size(); i++) bit[i] = 0;
	}
	void add(int pos, int x) {
		pos++;
		while (pos <= size_) {
			bit[pos] += x;
			pos += (pos & -pos);
		}
	}
	int sum(int pos) {
		int s = 0; pos++;
		while (pos >= 1) {
			s += bit[pos];
			pos -= (pos & -pos);
		}
		return s;
	}
};

class SegmentTree {
public:
	int size_ = 1;
	vector<int> counts;
	vector<int> idx;
	set<int> Tokusan[1 << 19];
	BIT Z;
	void init(int sz) {
		size_ = sz;
		idx.resize(size_ * 2 + 2, 0);
		counts.resize(size_ * 2 + 2, 0);
		Z.init(size_ * 2 + 2);
		for (int i = 0; i < counts.size(); i++) counts[i] = 0;
		for (int i = 0; i < counts.size(); i++) idx[i] = 0;
		for (int i = 0; i < size_ * 2 + 2; i++) Tokusan[i].clear();
	}
	int gettokusan(int x) {
		auto itr = Tokusan[x].begin();
		if (itr == Tokusan[x].end()) return -(1 << 30);
		return (*itr);
	}
	void dels(int pos) {
		counts[pos + size_]--;
		if (counts[pos + size_] == 0) {
			int val1 = gettokusan(idx[pos + size_]);
			if (val1 >= -(1 << 29)) Z.add(val1 + size_, -1);
			Tokusan[idx[pos + size_]].erase(pos);
			int val2 = gettokusan(idx[pos + size_]);
			if (val2 >= -(1 << 29)) Z.add(val2 + size_, 1);
			idx[pos + size_] = 0;
		}
	}
	void adds(int pos, int x) {
		counts[pos + size_]++;
		if (counts[pos + size_] == 1) {
			idx[pos + size_] = x;
			int val1 = gettokusan(idx[pos + size_]);
			if (val1 >= -(1 << 29)) Z.add(val1 + size_, -1);
			Tokusan[idx[pos + size_]].insert(pos);
			int val2 = gettokusan(idx[pos + size_]);
			if (val2 >= -(1 << 29)) Z.add(val2 + size_, 1);
		}
	}
	int getans(int pos) {
		return Z.sum(pos + size_);
	}
};

// ここからは個数を厳密に求めるやつ
int Answer[1 << 19], Fukasa[1 << 19];
SegmentTree Z0;

void dfs2(int pos, bool melee) {
	Fukasa[verdist[pos] + N] = pos;
	Answer[pos] = Z0.getans(verdist[pos] - maxdist[pos] - 1);

	// ランキングを求める
	vector<pair<int, int>> Ranking;
	for (int i : Y[pos]) Ranking.push_back(make_pair(maxdist[i], i));
	sort(Ranking.begin(), Ranking.end());

	// 再帰をする
	if (Ranking.size() >= 1) {
		int eval = -1;
		if (Ranking.size() >= 2) eval = Ranking[Ranking.size() - 2].first;
		for (int j = verdist[pos] - eval - 1; j <= verdist[pos] - 1; j++) Z0.dels(j);
		Z0.adds(verdist[pos], C[pos]);
		dfs2(Ranking[Ranking.size() - 1].second, true);
		Z0.dels(verdist[pos]);
		for (int j = verdist[pos] - eval - 1; j <= verdist[pos] - 1; j++) Z0.adds(j, C[Fukasa[j + N]]);
	}
	if (Ranking.size() >= 2) {
		for (int i = 0; i < (int)Ranking.size() - 1; i++) {
			Z0.adds(verdist[pos], C[pos]);
			dfs2(Ranking[i].second, false);
			Z0.dels(verdist[pos]);
		}
	}

	// 補正をする
	if (melee == false) {
		int eval = -1;
		if (Ranking.size() >= 1) eval = Ranking[Ranking.size() - 1].first;
		for (int i = verdist[pos] - eval - 1; i <= verdist[pos] - 1; i++) {
			Z0.adds(i, C[Fukasa[i + N]]);
		}
	}
	if (melee == true) {
		int v1 = verdist[pos] - 1;
		int v2 = verdist[pos] - maxdist[pos] - 1;
		int v3 = verdist[pos] - maxdist[pos] - 2;
		Z0.adds(v1, C[Fukasa[v1 + N]]);
		Z0.dels(v2);
		Z0.dels(v3);
	}
}

int main() {
	// ステップ 1. 入力
	scanf("%d%d", &N, &M);
	for (int i = 1; i <= N - 1; i++) scanf("%d%d", &A[i], &B[i]);
	for (int i = 1; i <= N; i++) scanf("%d", &C[i]);

	// ステップ 2. グラフの構成
	for (int i = 1; i <= N - 1; i++) {
		X[A[i]].push_back(B[i]);
		X[B[i]].push_back(A[i]);
	}

	// ステップ 3. 中心を求める
	vector<int> centroid = calc();
	for (int i : centroid) iscentroid[i] = true;

	// ステップ 4. 中心をグラフから外したグラフを考える
	for (int i = 1; i <= N; i++) maxdist[i] = -1;
	for (int i = 0; i < centroid.size(); i++) {
		int num = i;
		if (centroid.size() == 3) { if (i >= 1) num = 3 - i; }
		dfs1(centroid[i], num);
	}

	// ステップ 5. 珍しい都市の候補を判定する
	vector<int> cnt0(N, 0);
	vector<pair<int, int>> unique0;
	for (int i = 1; i <= N; i++) {
		if (label[i] != 0) continue;
		cnt0[verdist[i]]++;
	}
	for (int i = 1; i <= N; i++) {
		if (label[i] != 0 || cnt0[verdist[i]] >= 2) continue;
		unique0.push_back(make_pair(verdist[i], i));
	}
	vector<int> cnt1(N, 0);
	vector<pair<int, int>> unique1;
	for (int i = 1; i <= N; i++) {
		if (label[i] != 1) continue;
		cnt1[verdist[i]]++;
	}
	for (int i = 1; i <= N; i++) {
		if (label[i] != 1 || cnt1[verdist[i]] >= 2) continue;
		unique1.push_back(make_pair(verdist[i], i));
	}

	// ステップ 6. 深さ優先探索の前準備
	int offset = 1;
	if (centroid.size() == 3) offset = 2;
	int damage = 0;
	if (centroid.size() == 3) damage = maxdist[centroid[1]];

	// ステップ 7. 左側について、深さ優先探索を行う
	Z0.init(N);
	for (int i = 0; i < unique1.size(); i++) {
		Z0.adds(-unique1[i].first - offset, C[unique1[i].second]);
		Fukasa[-unique1[i].first - offset + N] = unique1[i].second;
	}
	if (offset == 2) { Z0.adds(-1, C[centroid[1]]); }
	for (int i = -offset + 1 - damage; i <= -offset; i++) Z0.dels(i);
	dfs2(centroid[0], false);

	// ステップ 8. 右側について、深さ優先探索を行う
	Z0.init(N);
	for (int i = 0; i < unique0.size(); i++) {
		Z0.adds(-unique0[i].first - offset, C[unique0[i].second]);
		Fukasa[-unique0[i].first - offset + N] = unique0[i].second;
	}
	if (offset == 2) { Z0.adds(-1, C[centroid[1]]); }
	for (int i = -offset + 1 - damage; i <= -offset; i++) Z0.dels(i);
	dfs2(centroid[offset], false);

	// ステップ 9. 中側について、深さ優先探索を行う
	if (offset == 2) {
		Z0.init(N);
		dfs2(centroid[1], false);
	}

	// ステップ 9. 出力する
	for (int i = 1; i <= N; i++) {
		if (M == 1) printf("%d\n", min(1, Answer[i]));
		else printf("%d\n", Answer[i]);
	}
	return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 108976
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#include <type_traits>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;

using ll=int64_t;
#define int ll

#define FOR(i,a,b) for(int i=int(a);i<int(b);i++)
#define REP(i,b) FOR(i,0,b)
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define ALL(x) x.begin(),x.end()
auto& errStream=cerr;
#ifdef LOCAL
#define cerr (cerr<<"-- line "<<__LINE__<<" -- ")
#else
class CerrDummy{}cerrDummy;
template<class T>
CerrDummy& operator<<(CerrDummy&cd,const T&){
	return cd;
}
using charTDummy=char;
using traitsDummy=char_traits<charTDummy>;
CerrDummy& operator<<(CerrDummy&cd,basic_ostream<charTDummy,traitsDummy>&(basic_ostream<charTDummy,traitsDummy>&)){
	return cd;
}
#define cerr cerrDummy
#endif
#define REACH cerr<<"reached"<<endl
#define DMP(x) cerr<<#x<<":"<<x<<endl
#define ZERO(x) memset(x,0,sizeof(x))
#define ONE(x) memset(x,-1,sizeof(x))

using pi=pair<int,int>;
using vi=vector<int>;
using ld=long double;

template<class T,class U>
ostream& operator<<(ostream& os,const pair<T,U>& p){
	os<<"("<<p.first<<","<<p.second<<")";
	return os;
}

template<class T>
ostream& operator <<(ostream& os,const vector<T>& v){
	os<<"{";
	REP(i,(int)v.size()){
		if(i)os<<",";
		os<<v[i];
	}
	os<<"}";
	return os;
}

ll read(){
	ll i;
	scanf("%"  SCNd64,&i);
	return i;
}

void printSpace(){
	printf(" ");
}

void printEoln(){
	printf("\n");
}

void print(ll x,int suc=1){
	printf("%" PRId64,x);
	if(suc==1)
		printEoln();
	if(suc==2)
		printSpace();
}

string readString(){
	static char buf[3341000];
	scanf("%s",buf);
	return string(buf);
}

char* readCharArray(){
	static char buf[3341000];
	static int bufUsed=0;
	char* ret=buf+bufUsed;
	scanf("%s",ret);
	bufUsed+=strlen(ret)+1;
	return ret;
}

template<class T,class U>
void chmax(T& a,U b){
	if(a<b)
		a=b;
}

template<class T,class U>
void chmin(T& a,U b){
	if(b<a)
		a=b;
}

template<class T>
T Sq(const T& t){
	return t*t;
}

#define CAPITAL
void Yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<endl;
	#else
	cout<<"Yes"<<endl;
	#endif
	if(ex)exit(0);
}
void No(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<endl;
	#else
	cout<<"No"<<endl;
	#endif
	if(ex)exit(0);
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

const int Nmax=200010;
vi tr[Nmax];
int ans[Nmax];
int col[Nmax],cnt[Nmax],curAns,stBuf[Nmax],stS;
void AddCol(int c){
	if(cnt[c]==0)
		curAns++;
	cnt[c]++;
}
void DelCol(int c){
	cnt[c]--;
	if(cnt[c]==0)
		curAns--;
}
void Push(int v){
	stBuf[stS++]=v;
	AddCol(col[v]);
}
bool Empty(){
	return stS==0;
}
int Last(){
	return stBuf[stS-1];
}
void Pop(){
	DelCol(col[Last()]);
	stS--;
}

void dfs1(int v,int p,int d,vi&dist){
	dist[v]=d;
	for(auto to:tr[v])
		if(to!=p)
			dfs1(to,v,d+1,dist);
}

int dep[Nmax];
int dfs2(int v,int p){
	int res=0;
	for(auto to:tr[v])
		if(to!=p)
			chmax(res,dfs2(to,v));
	return dep[v]=res+1;
}

void dfs3(int v,int p,const vi&dist){
	vector<pi> ch;
	for(auto to:tr[v])
		if(to!=p)
			ch.EB(dep[to],to);
	if(!ch.empty()){
		swap(ch[0],*max_element(ALL(ch)));
		int len=ch.size()>1?max_element(ch.begin()+1,ch.end())->first:0;
		for(auto c:ch){
			int to=c.second;
			while(!Empty()&&dist[Last()]>=dist[v]-len)
				Pop();
			Push(v);
			dfs3(to,v,dist);
			if(!Empty()&&Last()==v)
				Pop();
			chmax(len,c.first);
		}
		while(!Empty()&&dist[Last()]>=dist[v]-len)
			Pop();
	}
	chmax(ans[v],curAns);
}

void Solve(int root,const vi&dist){
	assert(Empty());
	dfs2(root,-1);
	dfs3(root,-1,dist);
}

signed main(){
	int n=read(),k=read();
	REP(_,n-1){
		int a=read()-1,b=read()-1;
		tr[a].PB(b);
		tr[b].PB(a);
	}
	REP(i,n)
		col[i]=read()-1;
	
	vi dist(n);
	dfs1(0,-1,0,dist);
	int root=max_element(ALL(dist))-dist.begin();
	dfs1(root,-1,0,dist);
	Solve(root,dist);
	
	root=max_element(ALL(dist))-dist.begin();
	dfs1(root,-1,0,dist);
	Solve(root,dist);
	
	REP(i,n)
		print(ans[i]);
}
accuracy: 1
time_ms: 330
memory_kb: 54364
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#include <type_traits>
using namespace std;

using ll=int64_t;
#define int ll

#define FOR(i,a,b) for(int i=int(a);i<int(b);i++)
#define REP(i,b) FOR(i,0,b)
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define ALL(x) x.begin(),x.end()
auto& errStream=cerr;
#ifdef LOCAL
#define cerr (cerr<<"-- line "<<__LINE__<<" -- ")
#else
class CerrDummy{}cerrDummy;
template<class T>
CerrDummy& operator<<(CerrDummy&cd,const T&){
	return cd;
}
using charTDummy=char;
using traitsDummy=char_traits<charTDummy>;
CerrDummy& operator<<(CerrDummy&cd,basic_ostream<charTDummy,traitsDummy>&(basic_ostream<charTDummy,traitsDummy>&)){
	return cd;
}
#define cerr cerrDummy
#endif
#define REACH cerr<<"reached"<<endl
#define DMP(x) cerr<<#x<<":"<<x<<endl
#define ZERO(x) memset(x,0,sizeof(x))
#define ONE(x) memset(x,-1,sizeof(x))

using pi=pair<int,int>;
using vi=vector<int>;
using ld=long double;

template<class T,class U>
ostream& operator<<(ostream& os,const pair<T,U>& p){
	os<<"("<<p.first<<","<<p.second<<")";
	return os;
}

template<class T>
ostream& operator <<(ostream& os,const vector<T>& v){
	os<<"{";
	REP(i,(int)v.size()){
		if(i)os<<",";
		os<<v[i];
	}
	os<<"}";
	return os;
}

ll read(){
	ll i;
	scanf("%"  SCNd64,&i);
	return i;
}

void printSpace(){
	printf(" ");
}

void printEoln(){
	printf("\n");
}

void print(ll x,int suc=1){
	printf("%" PRId64,x);
	if(suc==1)
		printEoln();
	if(suc==2)
		printSpace();
}

string readString(){
	static char buf[3341000];
	scanf("%s",buf);
	return string(buf);
}

char* readCharArray(){
	static char buf[3341000];
	static int bufUsed=0;
	char* ret=buf+bufUsed;
	scanf("%s",ret);
	bufUsed+=strlen(ret)+1;
	return ret;
}

template<class T,class U>
void chmax(T& a,U b){
	if(a<b)
		a=b;
}

template<class T,class U>
void chmin(T& a,U b){
	if(b<a)
		a=b;
}

template<class T>
T Sq(const T& t){
	return t*t;
}

#define CAPITAL
void Yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<endl;
	#else
	cout<<"Yes"<<endl;
	#endif
	if(ex)exit(0);
}
void No(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<endl;
	#else
	cout<<"No"<<endl;
	#endif
	if(ex)exit(0);
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

const int Nmax=200010;
vi tr[Nmax];
int ans[Nmax];
int col[Nmax],cnt[Nmax],curAns,stBuf[Nmax],stS;
void AddCol(int c){
	if(cnt[c]==0)
		curAns++;
	cnt[c]++;
}
void DelCol(int c){
	cnt[c]--;
	if(cnt[c]==0)
		curAns--;
}
void Push(int v){
	stBuf[stS++]=v;
	AddCol(col[v]);
}
bool Empty(){
	return stS==0;
}
int Last(){
	return stBuf[stS-1];
}
void Pop(){
	DelCol(col[Last()]);
	stS--;
}

void dfs1(int v,int p,int d,vi&dist){
	dist[v]=d;
	for(auto to:tr[v])
		if(to!=p)
			dfs1(to,v,d+1,dist);
}

int dep[Nmax];
int dfs2(int v,int p){
	int res=0;
	for(auto to:tr[v])
		if(to!=p)
			chmax(res,dfs2(to,v));
	return dep[v]=res+1;
}

void dfs3(int v,int p,const vi&dist){
	vector<pi> ch;
	for(auto to:tr[v])
		if(to!=p)
			ch.EB(dep[to],to);
	if(!ch.empty()){
		swap(ch[0],*max_element(ALL(ch)));
		int len=ch.size()>1?max_element(ch.begin()+1,ch.end())->first:0;
		for(auto c:ch){
			int to=c.second;
			while(!Empty()&&dist[Last()]>=dist[v]-len)
				Pop();
			Push(v);
			dfs3(to,v,dist);
			if(!Empty()&&Last()==v)
				Pop();
			chmax(len,c.first);
		}
		while(!Empty()&&dist[Last()]>=dist[v]-len)
			Pop();
	}
	chmax(ans[v],curAns);
}

void Solve(int root,const vi&dist){
	assert(Empty());
	dfs2(root,-1);
	dfs3(root,-1,dist);
}

signed main(){
	int n=read(),k=read();
	REP(_,n-1){
		int a=read()-1,b=read()-1;
		tr[a].PB(b);
		tr[b].PB(a);
	}
	REP(i,n)
		col[i]=read()-1;
	
	vi dist(n);
	dfs1(0,-1,0,dist);
	int root=max_element(ALL(dist))-dist.begin();
	dfs1(root,-1,0,dist);
	Solve(root,dist);
	
	root=max_element(ALL(dist))-dist.begin();
	dfs1(root,-1,0,dist);
	Solve(root,dist);
	
	REP(i,n)
		print(ans[i]);
}
accuracy: 1
time_ms: 350
memory_kb: 54452
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
template <bool Directed> struct graph {
    int n;
    vector<vector<int>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        adj[u].push_back(v);
        if(not Directed) adj[v].push_back(u);
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s) {
    vector<int> d(g.n + 1, -1);
    d[s] = 0;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        for(int v : g.adj[u]) {
            if(d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    vector<int> ans(n + 1);
    for(int s : diameter_nodes(g)) {
        vector<int> h(n + 1), max_subtree(n + 1), depth(n + 1), unique_cities;
        vector<int> unique_goods(m + 1);
        int n_unique = 0;
        function<void(int, int)> dfs1 = [&](int u, int from) {
            for(int v : g.adj[u]) {
                if(v != from) {
                    dfs1(v, u);
                    if(h[v] > h[max_subtree[u]]) max_subtree[u] = v;
                }
            }
            h[u] = h[max_subtree[u]] + 1;
        };
        dfs1(s, 0);
        function<void(int, int)> dfs2 = [&](int u, int from) {
            depth[u] = depth[from] + 1;
            auto add = [&](int v) {
                unique_cities.push_back(v);
                n_unique += ++unique_goods[c[v]] == 1;
            };
            auto remove = [&](int v) {
                if(not unique_cities.empty() and unique_cities.back() == v) {
                    unique_cities.pop_back();
                    n_unique -= unique_goods[c[v]]-- == 1;
                }
            };
            auto filter = [&](int max_allowed_depth) {
                while(not unique_cities.empty() and depth[unique_cities.back()] >= max_allowed_depth) {
                    remove(unique_cities.back());
                }
            };
            int n_children = g.adj[u].size() - bool(from);
            if(n_children >= 1) {
                if(n_children > 1) {
                    int second_max_subtree = 0;
                    for(int v : g.adj[u]) {
                        if(v != from and v != max_subtree[u] and h[v] > h[second_max_subtree]) {
                            second_max_subtree = v;
                        }
                    }
                    filter(depth[u] - h[second_max_subtree]);
                }
                add(u);
                dfs2(max_subtree[u], u);
                remove(u);
            }
            filter(depth[u] - (h[u] - 1));
            ans[u] = max(ans[u], n_unique);
            for(int v : g.adj[u]) {
                if(v != from and v != max_subtree[u]) {
                    add(u);
                    dfs2(v, u);
                    remove(u);
                }
            }
        };
        dfs2(s, 0);
    }
    for(int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 54668
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
template <bool Directed> struct graph {
    int n;
    vector<vector<int>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        adj[u].push_back(v);
        if(not Directed) adj[v].push_back(u);
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s) {
    vector<int> d(g.n + 1, -1);
    d[s] = 0;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        for(int v : g.adj[u]) {
            if(d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    vector<int> ans(n + 1);
    for(int s : diameter_nodes(g)) {
        vector<int> h(n + 1), max_subtree(n + 1), depth(n + 1), unique_cities;
        vector<int> unique_goods(m + 1);
        int n_unique = 0;
        function<void(int, int)> dfs1 = [&](int u, int from) {
            for(int v : g.adj[u]) {
                if(v != from) {
                    dfs1(v, u);
                    if(h[v] > h[max_subtree[u]]) max_subtree[u] = v;
                }
            }
            h[u] = h[max_subtree[u]] + 1;
        };
        dfs1(s, 0);
        function<void(int, int)> dfs2 = [&](int u, int from) {
            depth[u] = depth[from] + 1;
            auto add = [&](int v) {
                unique_cities.push_back(v);
                n_unique += ++unique_goods[c[v]] == 1;
            };
            auto remove = [&](int v) {
                if(not unique_cities.empty() and unique_cities.back() == v) {
                    unique_cities.pop_back();
                    n_unique -= unique_goods[c[v]]-- == 1;
                }
            };
            auto filter = [&](int max_allowed_depth) {
                while(not unique_cities.empty() and depth[unique_cities.back()] >= max_allowed_depth) {
                    remove(unique_cities.back());
                }
            };
            int n_children = g.adj[u].size() - bool(from);
            if(n_children >= 1) {
                if(n_children > 1) {
                    int second_max_subtree = 0;
                    for(int v : g.adj[u]) {
                        if(v != from and v != max_subtree[u] and h[v] > h[second_max_subtree]) {
                            second_max_subtree = v;
                        }
                    }
                    filter(depth[u] - h[second_max_subtree]);
                }
                add(u);
                dfs2(max_subtree[u], u);
                remove(u);
            }
            filter(depth[u] - (h[u] - 1));
            ans[u] = max(ans[u], n_unique);
            for(int v : g.adj[u]) {
                if(v != from and v != max_subtree[u]) {
                    add(u);
                    dfs2(v, u);
                    remove(u);
                }
            }
        };
        dfs2(s, 0);
    }
    for(int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 54620
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
template <bool Directed> struct graph {
    int n;
    vector<vector<int>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        adj[u].push_back(v);
        if(not Directed) adj[v].push_back(u);
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s) {
    vector<int> d(g.n + 1, -1);
    d[s] = 0;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        for(int v : g.adj[u]) {
            if(d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    vector<int> ans(n + 1);
    for(int s : diameter_nodes(g)) {
        vector<int> h(n + 1), max_subtree(n + 1), depth(n + 1), unique_cities;
        map<int, int> unique_goods;
        function<void(int, int)> dfs1 = [&](int u, int from) {
            for(int v : g.adj[u]) {
                if(v != from) {
                    dfs1(v, u);
                    if(h[v] > h[max_subtree[u]]) max_subtree[u] = v;
                }
            }
            h[u] = h[max_subtree[u]] + 1;
        };
        dfs1(s, 0);
        function<void(int, int)> dfs2 = [&](int u, int from) {
            depth[u] = depth[from] + 1;
            auto add = [&](int v) {
                unique_cities.push_back(v);
                unique_goods[c[v]]++;
            };
            auto remove = [&](int v) {
                if(not unique_cities.empty() and unique_cities.back() == v) {
                    unique_cities.pop_back();
                    if(--unique_goods[c[v]] == 0) {
                        unique_goods.erase(c[v]);
                    }
                }
            };
            auto filter = [&](int max_allowed_depth) {
                while(not unique_cities.empty() and depth[unique_cities.back()] >= max_allowed_depth) {
                    remove(unique_cities.back());
                }
            };
            int n_children = g.adj[u].size() - bool(from);
            if(n_children >= 1) {
                if(n_children > 1) {
                    int second_max_subtree = 0;
                    for(int v : g.adj[u]) {
                        if(v != from and v != max_subtree[u] and h[v] > h[second_max_subtree]) {
                            second_max_subtree = v;
                        }
                    }
                    filter(depth[u] - h[second_max_subtree]);
                }
                add(u);
                dfs2(max_subtree[u], u);
                remove(u);
            }
            filter(depth[u] - (h[u] - 1));
            ans[u] = max(ans[u], int(unique_goods.size()));
            for(int v : g.adj[u]) {
                if(v != from and v != max_subtree[u]) {
                    add(u);
                    dfs2(v, u);
                    remove(u);
                }
            }
        };
        dfs2(s, 0);
    }
    for(int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 670
memory_kb: 65356
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else if(*min_element(c.begin() + 1, c.end()) == 1 and *max_element(c.begin() + 1, c.end()) == 1) {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, int)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            vector<int> unique_depths, temp;
            unique_depths.reserve(n);
            temp.reserve(n);
            function<void(int, int, int)> dfs2 = [&](int u, int from, int depth) {
                int temp_size = 0;
                while(not unique_depths.empty() and unique_depths.back() >= depth - (h[u] - 1)) {
                    temp.push_back(unique_depths.back());
                    temp_size++;
                    unique_depths.pop_back();
                }
                ans[u] = max(ans[u], int(unique_depths.size()));
                unique_depths.push_back(depth);
                for(int i = 1; i + 1 < g.adj[u].size(); i++) {
                    dfs2(g.adj[u][i].v, u, depth + 1);
                }
                unique_depths.pop_back();
                while(temp_size) {
                    unique_depths.push_back(temp.back());
                    temp.pop_back();
                    temp_size--;
                }
                if(g.adj[u].size() > 1 and g.adj[u][1].v != from) {
                    while(not unique_depths.empty() and unique_depths.back() >= depth - h[g.adj[u][1].v]) {
                        temp.push_back(unique_depths.back());
                        temp_size++;
                        unique_depths.pop_back();
                    }
                    unique_depths.push_back(depth);
                    dfs2(g.adj[u][0].v, u, depth + 1);
                    unique_depths.pop_back();
                    while(temp_size) {
                        unique_depths.push_back(temp.back());
                        temp.pop_back();
                        temp_size--;
                    }
                }
            };
            dfs2(s, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.4608695652173913
time_ms: 420
memory_kb: 41944
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else if(*min_element(c.begin() + 1, c.end()) == 1 and *max_element(c.begin() + 1, c.end()) == 1) {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, int)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            vector<int> unique_depths, temp;
            function<void(int, int, int)> dfs2 = [&](int u, int from, int depth) {
                auto pos = lower_bound(unique_depths.begin(), unique_depths.end(), depth - (h[u] - 1)) - unique_depths.begin();
                ans[u] = max(ans[u], int(pos));
                int n_children = g.adj[u].size() - bool(from);
                if(n_children == 1) {
                    unique_depths.push_back(depth);
                    for(auto& e : g.adj[u]) {
                        if(e.v != from) {
                            dfs2(e.v, u, depth + 1);
                        }
                    }
                    unique_depths.pop_back();
                } else if(n_children > 1) {
                    int temp_size = 0;
                    while(not unique_depths.empty() and unique_depths.back() >= depth - (h[u] - 1)) {
                        temp.push_back(unique_depths.back());
                        temp_size++;
                        unique_depths.pop_back();
                    }
                    for(int i = 1; i + 1 < g.adj[u].size(); i++) {
                        int v = g.adj[u][i].v;
                        unique_depths.push_back(depth);
                        dfs2(v, u, depth + 1);
                        unique_depths.pop_back();
                    }
                    while(temp_size--) {
                        unique_depths.push_back(temp.back());
                        temp.pop_back();
                    }
                    while(not unique_depths.empty() and unique_depths.back() >= depth - h[g.adj[u][1].v]) {
                        temp.push_back(unique_depths.back());
                        temp_size++;
                        unique_depths.pop_back();
                    }
                    unique_depths.push_back(depth);
                    dfs2(g.adj[u][0].v, u, depth + 1);
                    unique_depths.pop_back();
                    while(temp_size--) {
                        unique_depths.push_back(temp.back());
                        temp.pop_back();
                    }
                }
            };
            dfs2(s, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.4608695652173913
time_ms: 410
memory_kb: 41772
final_rank: 14

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
template <bool Directed> struct graph {
    int n;
    vector<vector<int>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        adj[u].push_back(v);
        if(not Directed) adj[v].push_back(u);
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(int v : g.adj[u]) {
            if(d[v] == -1) {
                d[v] = d[u] + 1, p[v] = u;
                q.push(v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
const int N = 200'000;
int ans[N + 1], h[N + 1];
void dfs1(graph<0>& g, int u, int from = 0) {
    for(int v : g.adj[u]) {
        if(v != from) {
            dfs1(g, v, u);
        }
    }
    sort(g.adj[u].begin(), g.adj[u].end(), [&](int v1, int v2) {
        return v2 == from or (v1 != from and h[v1] > h[v2]);
    });
    h[u] = h[g.adj[u][0]] + 1;
}
vector<int> unique_depths, temp;
int depth = 0;
void dfs2(graph<0>& g, int u, int from = 0) {
    auto pos = lower_bound(unique_depths.begin(), unique_depths.end(), depth - (h[u] - 1)) - unique_depths.begin();
    ans[u] = max(ans[u], int(pos));
    int n_children = g.adj[u].size() - bool(from);
    if(n_children == 1) {
        unique_depths.push_back(depth);
        for(int v : g.adj[u]) {
            if(v != from) {
                depth++;
                dfs2(g, v, u);
                depth--;
            }
        }
        unique_depths.pop_back();
    } else if(n_children > 1) {
        while(not unique_depths.empty() and unique_depths.back() >= depth - (h[u] - 1)) {
            temp.push_back(unique_depths.back());
            unique_depths.pop_back();
        }
        for(int i = 1; i + 1 < g.adj[u].size(); i++) {
            unique_depths.push_back(depth);
            depth++;
            dfs2(g, g.adj[u][i], u);
            depth--;
            unique_depths.pop_back();
        }
        while(not temp.empty()) {
            unique_depths.push_back(temp.back());
            temp.pop_back();
        }
        while(not unique_depths.empty() and unique_depths.back() >= depth - h[g.adj[u][1]]) {
            temp.push_back(unique_depths.back());
            unique_depths.pop_back();
        }
        unique_depths.push_back(depth);
        depth++;
        dfs2(g, g.adj[u][0], u);
        depth--;
        unique_depths.pop_back();
        while(not temp.empty()) {
            unique_depths.push_back(temp.back());
            temp.pop_back();
        }
    }
};
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else if(*min_element(c.begin() + 1, c.end()) == 1 and *max_element(c.begin() + 1, c.end()) == 1) {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(int v : g.adj[u]) {
                    if(v != from) {
                        dfs1(v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](int v1, int v2) {
                    return v2 == from or (v1 != from and h[v1] > h[v2]);
                });
                h[u] = h[g.adj[u][0]] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, int)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(int v : g.adj[u]) {
                    if(v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0] == v ? g.adj[u][1] : g.adj[u][0];
                        dfs2(v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    } else {
        for(int s : diameter_nodes(g)) {
            memset(h, 0, sizeof h);
            dfs1(g, s);
            dfs2(g, s);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.4608695652173913
time_ms: 410
memory_kb: 37932
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else if(*min_element(c.begin(), c.end()) == 1 and *max_element(c.begin(), c.end()) == 1) {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, int)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, vector<int>&)> dfs2 = [&](int u, int from, int depth, vector<int>& unique_depths) {
                auto pos = lower_bound(unique_depths.begin(), unique_depths.end(), depth - (h[u] - 1)) - unique_depths.begin();
                ans[u] = max(ans[u], int(pos));
                int n_children = g.adj[u].size() - bool(from);
                if(n_children == 1) {
                    unique_depths.push_back(depth);
                    for(auto& e : g.adj[u]) {
                        if(e.v != from) {
                            dfs2(e.v, u, depth + 1, unique_depths);
                        }
                    }
                    unique_depths.pop_back();
                } else if(n_children > 1) {
                    vector<int> temp;
                    while(not unique_depths.empty() and unique_depths.back() >= depth - (h[u] - 1)) {
                        temp.push_back(unique_depths.back());
                        unique_depths.pop_back();
                    }
                    for(int i = 1; i + 1 < g.adj[u].size(); i++) {
                        int v = g.adj[u][i].v;
                        unique_depths.push_back(depth);
                        dfs2(v, u, depth + 1, unique_depths);
                        unique_depths.pop_back();
                    }
                    while(not temp.empty()) {
                        unique_depths.push_back(temp.back());
                        temp.pop_back();
                    }
                    while(not unique_depths.empty() and unique_depths.back() >= depth - h[g.adj[u][1].v]) {
                        temp.push_back(unique_depths.back());
                        unique_depths.pop_back();
                    }
                    unique_depths.push_back(depth);
                    dfs2(g.adj[u][0].v, u, depth + 1, unique_depths);
                    unique_depths.pop_back();
                    while(not temp.empty()) {
                        unique_depths.push_back(temp.back());
                        temp.pop_back();
                    }
                }
            };
            vector<int> unique_depths;
            dfs2(s, 0, 0, unique_depths);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.3130434782608696
time_ms: 230
memory_kb: 13900
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, int)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.4608695652173913
time_ms: 450
memory_kb: 41972
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, bool)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, not u_has_one_child and depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.3130434782608696
time_ms: 240
memory_kb: 13852
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, bool)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 0, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.3130434782608696
time_ms: 230
memory_kb: 13816
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
struct edge { int u, v, i; };
ostream& operator<<(ostream& os, const edge& e) {
    os << "(" << e.u << ", " << e.v << ")";
    return os;
}
template <bool Directed> struct graph {
    int n;
    vector<edge> edges;
    vector<vector<edge>> adj;
    graph(int n) : n(n), adj(n + 1) {}
    void add_edge(int u, int v) {
        int i = edges.size();
        edges.push_back({u, v, i});
        adj[u].push_back({u, v, i});
        if(not Directed) adj[v].push_back({v, u, i});
    }
};
template <bool Directed> vector<int> bfs(graph<Directed>& g, int s, const function<void(int)>& f = [](int) {}) {
    vector<int> d(g.n + 1, -1), p(g.n + 1);
    d[s] = 0, p[s] = -1;
    queue<int> q({s});
    while(not q.empty()) {
        int u = q.front(); q.pop();
        f(u);
        for(auto& e : g.adj[u]) {
            if(d[e.v] == -1) {
                d[e.v] = d[u] + 1, p[e.v] = u;
                q.push(e.v);
            }
        }
    }
    return d;
}
vector<int> diameter_nodes(graph<0>& g) {
    auto d1 = bfs(g, 1);
    int n1 = max_element(d1.begin(), d1.end()) - d1.begin();
    auto d2 = bfs(g, n1);
    int n2 = max_element(d2.begin(), d2.end()) - d2.begin();
    return {n1, n2};
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    graph<0> g(n);
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    vector<int> c(n + 1);
    for(int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    if(n <= 2000) {
        for(int i = 1; i <= n; i++) {
            auto d = bfs(g, i);
            vector<int> n_dist(n + 1);
            for(int j = 1; j <= n; j++) {
                if(j != i) {
                    n_dist[d[j]]++;
                }
            }
            set<int> ans;
            for(int j = 1; j <= n; j++) {
                if(n_dist[d[j]] == 1) {
                    ans.insert(c[j]);
                }
            }
            cout << ans.size() << endl;
        }
    } else {
        vector<int> ans(n + 1);
        for(int s : diameter_nodes(g)) {
            vector<int> h(n + 1);
            function<void(int, int)> dfs1 = [&](int u, int from) {
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        dfs1(e.v, u);
                    }
                }
                sort(g.adj[u].begin(), g.adj[u].end(), [&](auto& e1, auto& e2) {
                    return e2.v == from or (e1.v != from and h[e1.v] > h[e2.v]);
                });
                h[u] = h[g.adj[u][0].v] + 1;
            };
            dfs1(s, 0);
            function<void(int, int, int, bool)> dfs2 = [&](int u, int from, int depth, int lowest_unique) {
                ans[u] |= depth - (h[u] - 1) > lowest_unique;
                bool u_has_one_child = g.adj[u].size() - bool(from) == 1;
                for(auto& e : g.adj[u]) {
                    if(e.v != from) {
                        int tallest_sibling = not u_has_one_child and g.adj[u][0].v == e.v ? g.adj[u][1].v : g.adj[u][0].v;
                        dfs2(e.v, u, depth + 1, depth - h[tallest_sibling] <= lowest_unique ? depth : lowest_unique);
                    }
                }
            };
            dfs2(s, 0, 1, 0);
        }
        for(int i = 1; i <= n; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
accuracy: 0.3130434782608696
time_ms: 230
memory_kb: 13796
final_rank: 17