#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <vector> using namespace std; struct Rhine_Lab { Rhine_Lab() { freopen("tree.in", "r", stdin); freopen("tree.out", "w", stdout); } }; Rhine_Lab Ptilopsis_w;
const int N = 1e6+10;
namespace tr { struct node { int ls, rs; int cnt, sum; bool all; } a[N*10]; int root[N], node_cnt, lim; void add(int &i, int pos, int l = 1, int r = lim); void merge(int &x, int &y, int l = 1, int r = lim); int query(int x); } namespace tree { int len1[N], len2[N], falen[N]; void prework1(int x, int fa); void prework2(int x, int fa); } using namespace tr; using namespace tree;
int n, m, ans; int tot[N]; int dis[N], col[N]; vector<int> ver[N];
void dfs(int x, int fa);
int main() { cin >> n >> m; for(int i = 1; i <= n; i++) cin >> col[i], tot[col[i]]++; for(int i = 1; i < n; i++) { int a, b; cin >> a >> b; ver[a].push_back(b); ver[b].push_back(a); } tree::prework1(1, 0); tree::prework2(1, 0); tr::lim = m; dfs(1, 0); cout << ans << "\n"; }
void dfs(int x, int fa) { tr::add(root[x], col[x]); for(auto y : ver[x]) { if(y == fa) continue; dfs(y, x); merge(root[x], root[y]); } if(a[root[x]].sum == m) ans = max(ans, falen[x]+1); if(!a[root[x]].all) ans = max(ans, len1[x]+2); }
namespace tree { void prework1(int x, int fa) { len1[x] = -1e9; len2[x] = -1e9; for(auto y : ver[x]) { if(y == fa) continue; prework1(y, x); if(len1[y]+1 > len1[x]) { len2[x] = len1[x]; len1[x] = len1[y]+1; } else if(len1[y]+1 > len2[x]) len2[x] = len1[y]+1; } len1[x] = max(len1[x], 0); } void prework2(int x, int fa) { for(auto y : ver[x]) { if(y == fa) continue; if(len1[y]+1 == len1[x]) falen[y] = max(falen[x], len2[x]) + 1; else falen[y] = max(falen[x], len1[x]) + 1; prework2(y, x); } } }
namespace tr { #define ls(i) a[i].ls #define rs(i) a[i].rs #define lmid ((l+r)>>1) #define rmid ((l+r+2)>>1) vector<int> bin; int newnode() { int x; if(bin.size()) x = bin.back(), bin.pop_back(); else x = ++node_cnt; a[x].all = a[x].cnt = a[x].ls = a[x].rs = a[x].sum = 0; return x; } void pushup(int i) { a[i].sum = a[ls(i)].sum + a[rs(i)].sum; a[i].all = a[ls(i)].all | a[rs(i)].all; } void add(int &i, int pos, int l, int r) { if(!i) i = newnode(); if(l == r) { a[i].cnt++; a[i].sum |= 1; a[i].all = (a[i].cnt==tot[l]); return void(); } if(pos <= lmid) add(ls(i), pos, l, lmid); if(pos >= rmid) add(rs(i), pos, rmid, r); pushup(i); } void merge(int &x, int &y, int l, int r) { if(!x or !y) return void(x = x|y); if(l == r) { a[x].cnt += a[y].cnt; a[x].sum |= a[y].sum; a[x].all = (a[x].cnt == tot[l]); return void(); } merge(ls(x), ls(y), l, lmid); merge(rs(x), rs(y), rmid, r); bin.push_back(y); pushup(x); } }
|