#include <bits/stdc++.h>
using namespace std;
struct HLD {
  int n;
  vector<vector<int>> adj;
  vector<int> sz, in, out, head, rev, par, depth;
  HLD(int n)
      : n(n), adj(n), sz(n), in(n), out(n), head(n), rev(n), par(n), depth(n) {}
  void add_edge(int a, int b) {
    assert(0 <= a && a < n && 0 <= b && b < n);
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  void dfs_sz(int v, int p, int d) {
    par[v] = p;
    sz[v] = 1;
    depth[v] = d;
    if (!adj[v].empty() && adj[v][0] == p) swap(adj[v][0], adj[v].back());
    for (int &s : adj[v]) {
      if (s == p) continue;
      dfs_sz(s, v, d + 1);
      sz[v] += sz[s];
      if (sz[adj[v][0]] < sz[s]) swap(adj[v][0], s);
    }
  }
  void dfs_hld(int v, int p, int &times) {
    in[v] = times++;
    rev[in[v]] = v;
    for (int &s : adj[v]) {
      if (s == p) continue;
      head[s] = adj[v][0] == s ? head[v] : s;
      dfs_hld(s, v, times);
    }
    out[v] = times;
  }
  void build() {
    dfs_sz(0, -1, 0);
    int t = 0;
    dfs_hld(0, -1, t);
  }
  int la(int v, int k) {
    while (1) {
      int u = head[v];
      if (in[v] - k >= in[u]) return rev[in[v] - k];
      k -= in[v] - in[u] + 1;
      v = par[u];
    }
  }
  int lca(int u, int v) {
    for (;; v = par[head[v]]) {
      if (in[u] > in[v]) swap(u, v);
      if (head[u] == head[v]) return u;
    }
  }
  template <typename Q, typename F, typename T>
  T query(int u, int v, const Q &q, const F &f, const T &e, bool edge = false) {
    T l = e, r = e;
    for (;; v = par[head[v]]) {
      if (in[u] > in[v]) swap(u, v), swap(l, r);
      if (head[u] == head[v]) break;
      l = f(q(in[head[v]], in[v]), l);
    }
    return f(f(q(in[u] + edge, in[v]), l), r);
  }
  template <typename Q>
  void update(int u, int v, const Q &q, bool edge = false) {
    for (;; v = par[head[v]]) {
      if (in[u] > in[v]) swap(u, v);
      if (head[u] == head[v]) break;
      q(in[head[v]], in[v]);
    }
    q(in[u] + edge, in[v]);
  }
};
int cnt[101010];
int cntrev[101010];
struct Mo {
  int block;
  vector<int> order, le, ri, ks;
  vector<bool> visited;
  function<void(int)> add, del;
  int nl, nr;
  Mo() {}
  Mo(int n, function<void(int)> add, function<void(int)> del)
      : block((int)sqrt(n)),
        nl(0),
        nr(0),
        visited(n),
        add(move(add)),
        del(move(del)){};
  void add_query(int l, int r, int k) {
    le.push_back(l);
    ri.push_back(r);
    ks.push_back(k);
  }
  void shift(int idx) {
    visited[idx].flip();
    if (visited[idx])
      add(idx);
    else
      del(idx);
  }
  vector<int> answer() {
    int qcnt = le.size();
    order.resize(qcnt);
    vector<int> ret(qcnt);
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(), [&](int a, int b) {
      return le[a] / block != le[b] / block ? le[a] < le[b] : ri[a] < ri[b];
    });
    for (int i = 0; i < qcnt; i++) {
      int idx = order[i];
      while (nl > le[idx]) shift(--nl);
      while (nr < ri[idx]) shift(nr++);
      while (nl < le[idx]) shift(nl++);
      while (nr > ri[idx]) shift(--nr);
      ret[idx] = cntrev[ks[idx]];
    }
    return ret;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> as(n);
  for (int i = 0; i < n; i++) {
    cin >> as[i];
  }
  HLD hld(n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    hld.add_edge(a, b);
  }
  hld.build();
  auto add = [&](int idx) { cntrev[++cnt[as[hld.rev[idx]]]]++; };
  auto del = [&](int idx) { cntrev[cnt[as[hld.rev[idx]]]--]--; };
  cout << endl;
  Mo mo(n, add, del);
  while (m--) {
    int v, k;
    cin >> v >> k;
    v--;
    mo.add_query(hld.in[v], hld.out[v], k);
  }
  for (int a : mo.answer()) {
    cout << a << '\n';
  }
}
