#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 5;
struct segment_change {
  int add;
  segment_change(int _add = 0) : add(_add) {}
  void reset() { add = 0; }
  segment_change combine(const segment_change &other) const {
    return segment_change(add + other.add);
  }
};
struct segment {
  int minimum, count;
  segment(int _minimum = INF, int _count = 0)
      : minimum(_minimum), count(_count) {}
  void apply(int start, int end, const segment_change &change) {
    minimum += change.add;
  }
  void join(const segment &other) {
    if (other.minimum < minimum)
      *this = other;
    else if (other.minimum == minimum)
      count += other.count;
  }
  void join(const segment &a, const segment &b) {
    *this = a;
    join(b);
  }
};
struct seg_tree {
  int tree_n;
  vector<segment> tree;
  vector<segment_change> changes;
  seg_tree(int n = 0) {
    tree_n = 0;
    if (n > 0) init(n);
  }
  void init(int n) {
    tree_n = 1;
    while (tree_n < n) tree_n *= 2;
    tree.assign(2 * tree_n, segment());
    changes.assign(2 * tree_n, segment_change());
  }
  void build(const vector<segment> &initial) {
    int n = initial.size();
    assert(n <= tree_n);
    for (int i = 0; i < n; i++) tree[tree_n + i] = initial[i];
    for (int position = tree_n - 1; position > 0; position--)
      tree[position].join(tree[2 * position], tree[2 * position + 1]);
  }
  void push_down(int position, int start, int mid, int end) {
    tree[2 * position].apply(start, mid, changes[position]);
    tree[2 * position + 1].apply(mid, end, changes[position]);
    changes[2 * position] = changes[2 * position].combine(changes[position]);
    changes[2 * position + 1] =
        changes[2 * position + 1].combine(changes[position]);
    changes[position].reset();
  }
  template <typename T_range_op, typename T_join_op>
  void process_range(int position, int start, int end, int a, int b,
                     T_range_op &&range_op, T_join_op &&join_op) {
    if (a <= start && end <= b) {
      range_op(position, start, end);
      return;
    }
    if (position >= tree_n) return;
    int mid = (start + end) / 2;
    push_down(position, start, mid, end);
    if (a < mid)
      process_range(2 * position, start, mid, a, b, range_op, join_op);
    if (b > mid)
      process_range(2 * position + 1, mid, end, a, b, range_op, join_op);
    join_op(position);
  }
  segment query(int a, int b) {
    segment answer;
    process_range(
        1, 0, tree_n, a, b,
        [&](int position, int, int) { answer.join(tree[position]); },
        [&](int) {});
    return answer;
  }
  void update(int a, int b, const segment_change &change) {
    process_range(
        1, 0, tree_n, a, b,
        [&](int position, int start, int end) {
          tree[position].apply(start, end, change);
          changes[position] = changes[position].combine(change);
        },
        [&](int position) {
          tree[position].join(tree[2 * position], tree[2 * position + 1]);
        });
  }
};
int N, Q;
vector<vector<int>> adj;
vector<int> tour_start, tour_end;
int tour;
void dfs(int node, int parent) {
  if (parent == -1) tour = 0;
  tour_start[node] = tour++;
  if (parent != -1)
    adj[node].erase(find(adj[node].begin(), adj[node].end(), parent));
  for (int neighbor : adj[node])
    if (neighbor != parent) dfs(neighbor, node);
  tour_end[node] = tour;
}
bool is_ancestor(int u, int v) {
  return tour_start[u] <= tour_start[v] && tour_end[v] <= tour_end[u];
}
seg_tree tree;
void update_back_edge(int u, int v, int direction) {
  assert(!adj[u].empty());
  int low = 0, high = adj[u].size() - 1;
  while (low < high) {
    int mid = (low + high) / 2;
    if (tour_end[adj[u][mid]] >= tour_start[v])
      high = mid;
    else
      low = mid + 1;
  }
  int u_child = adj[u][low];
  assert(is_ancestor(u_child, v));
  tree.update(tour_start[u_child], tour_end[u_child],
              segment_change(direction));
  tree.update(tour_start[v], tour_end[v], segment_change(-direction));
}
void update_cross_edge(int u, int v, int direction) {
  tree.update(0, tree.tree_n, segment_change(direction));
  tree.update(tour_start[u], tour_end[u], segment_change(-direction));
  tree.update(tour_start[v], tour_end[v], segment_change(-direction));
}
void update(int u, int v, int direction) {
  if (is_ancestor(u, v))
    update_back_edge(u, v, direction);
  else if (is_ancestor(v, u))
    update_back_edge(v, u, direction);
  else
    update_cross_edge(u, v, direction);
}
int main() {
  scanf("%d %d", &N, &Q);
  adj.assign(N, {});
  for (int i = 0; i < N - 1; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    u--;
    v--;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  tour_start.resize(N);
  tour_end.resize(N);
  dfs(0, -1);
  tree.init(N);
  tree.build(vector<segment>(N, segment(0, 1)));
  set<pair<int, int>> contained;
  for (int q = 0; q < Q; q++) {
    int u, v;
    scanf("%d %d", &u, &v);
    u--;
    v--;
    if (u > v) swap(u, v);
    int direction = +1;
    if (!contained.insert({u, v}).second) {
      contained.erase({u, v});
      direction = -1;
    }
    update(u, v, direction);
    const segment &all = tree.query(0, tree.tree_n);
    printf("%d\n", all.minimum == 0 ? all.count : 0);
  }
}
