#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);     } }
   |