Problem p03727 (C++)

Buggy submission (status: Runtime Error):
#include <cstdio>
#include <utility>
#include <vector>

struct node_t {
  std::vector<int> data;
  std::pair<int, int> answer;
  int lazy;
};

int n;
std::pair<int, int> saved_edges[100010];
bool removed[100010];
std::vector<int> edges[100010];
int size[100010], son[100010], top[100010], deep[100010], dfn[100010];
int father[100010];
struct node_t nodes[300030];
int qx, ql, qr;

void dfs0(int x, int y) {
  int e;

  father[x] = y;
  deep[x] = deep[y] + 1;
  size[x] = 1;
  for (e = 0; e < edges[x].size(); ++e)
    if (edges[x][e] != y)
      dfs0(edges[x][e], x), size[x] += size[edges[x][e]],
          son[x] = (!son[x] || size[son[x]] < size[edges[x][e]]) ? edges[x][e]
                                                                 : son[x];
}

void dfs(int x, int y, int z) {
  static int total = 1;
  int e;

  top[x] = z;
  dfn[x] = total++;
  if (son[x])
    dfs(son[x], x, z);
  for (e = 0; e < edges[x].size(); ++e)
    if (edges[x][e] != y && edges[x][e] != son[x])
      dfs(edges[x][e], x, edges[x][e]);
}

inline void node_update(int x) {
  nodes[x].answer = std::min(nodes[x << 1].answer, nodes[(x << 1) | 1].answer);
}

inline void node_pushdown(int x) {
  nodes[x << 1].lazy += nodes[x].lazy;
  nodes[(x << 1) | 1].lazy += nodes[x].lazy;
  nodes[(x << 1) | 1].answer.first += nodes[x].lazy;
  nodes[x << 1].answer.first += nodes[x].lazy;
  nodes[x].lazy = 0;
}

void tree_insert(int x, int l, int r) {
  if (ql > r || qr < l)
    return;
  if (ql <= l && r <= qr) {
    nodes[x].data.push_back(qx);
    ++nodes[x].lazy;
    ++nodes[x].answer.first;
    return;
  }
  node_pushdown(x);
  tree_insert(x << 1, l, (l + r) >> 1);
  tree_insert((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

void tree_remove(int x, int l, int r) {
  if (ql > r || qr < l)
    return;
  if (ql <= l && r <= qr) {
    --nodes[x].lazy;
    --nodes[x].answer.first;
    return;
  }
  node_pushdown(x);
  tree_remove(x << 1, l, (l + r) >> 1);
  tree_remove((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

int tree_get(int x, int l, int r) {
  int k;

  for (k = 0; k < nodes[x].data.size(); ++k)
    if (!removed[nodes[x].data[k]])
      break;
  if (k != nodes[x].data.size())
    k = nodes[x].data[0] = nodes[x].data[k], nodes[x].data.resize(1);
  else
    nodes[x].data.clear(), k = 0;

  if (l == r) {
    nodes[x].answer.first = 0x7f7f7f7f;
    return k;
  }

  node_pushdown(x);
  if (qx <= (l + r) >> 1)
    k += tree_get(x << 1, l, (l + r) >> 1);
  else
    k += tree_get((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
  return k;
}

void tree_build(int x, int l, int r) {
  if (l == r) {
    nodes[x].answer.second = l;
    return;
  }
  tree_build(x << 1, l, (l + r) >> 1);
  tree_build((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

int lca(int x, int y) {
  while (top[x] != top[y])
    if (deep[top[x]] > deep[top[y]])
      x = father[top[x]];
    else
      y = father[top[y]];
  return deep[x] > deep[y] ? y : x;
}

void cover(int x, int y, bool z) {
  while (top[x] != top[y])
    ql = dfn[top[x]], qr = dfn[x], tree_insert(1, 2, n), x = father[top[x]];
  if (z || x != y)
    ql = dfn[y] + (z ? 0 : 1), qr = dfn[x], tree_insert(1, 2, n);
}

void uncover(int x, int y, bool z) {
  while (top[x] != top[y])
    ql = dfn[top[x]], qr = dfn[x], tree_remove(1, 2, n), x = father[top[x]];
  if (z || x != y)
    ql = dfn[y] + (z ? 0 : 1), qr = dfn[x], tree_remove(1, 2, n);
}

int main(void) {
  int i;
  int u, v, w;

  freopen("x.in", "r", stdin);

  scanf("%d", &n);
  for (i = 1; i <= n - 1; ++i)
    scanf("%d %d", &u, &v), edges[u].push_back(v), edges[v].push_back(u);

  dfs0(1, 0);
  dfs(1, 0, 1);
  tree_build(1, 2, n);

  for (i = 1; i <= n - 1; ++i) {
    scanf("%d %d", &u, &v);
    saved_edges[i].first = u;
    saved_edges[i].second = v;
    qx = i;
    w = lca(u, v);
    cover(u, w, 0);
    cover(v, w, 0);
  }

  for (i = 1; i <= n - 1; ++i) {
    if (nodes[1].answer.first != 1)
      return puts("NO"), 0;
    qx = nodes[1].answer.second;
    w = tree_get(1, 2, n);
    removed[w] = 1;
    u = saved_edges[w].first;
    v = saved_edges[w].second;
    w = lca(u, v);
    uncover(u, w, 0);
    uncover(v, w, 0);
  }
  puts("YES");

  return 0;
}

Fixed submission:
#include <cstdio>
#include <utility>
#include <vector>

struct node_t {
  std::vector<int> data;
  std::pair<int, int> answer;
  int lazy;
};

int n;
std::pair<int, int> saved_edges[100010];
bool removed[100010];
std::vector<int> edges[100010];
int size[100010], son[100010], top[100010], deep[100010], dfn[100010];
int father[100010];
struct node_t nodes[300030];
int qx, ql, qr;

void dfs0(int x, int y) {
  int e;

  father[x] = y;
  deep[x] = deep[y] + 1;
  size[x] = 1;
  for (e = 0; e < edges[x].size(); ++e)
    if (edges[x][e] != y)
      dfs0(edges[x][e], x), size[x] += size[edges[x][e]],
          son[x] = (!son[x] || size[son[x]] < size[edges[x][e]]) ? edges[x][e]
                                                                 : son[x];
}

void dfs(int x, int y, int z) {
  static int total = 1;
  int e;

  top[x] = z;
  dfn[x] = total++;
  if (son[x])
    dfs(son[x], x, z);
  for (e = 0; e < edges[x].size(); ++e)
    if (edges[x][e] != y && edges[x][e] != son[x])
      dfs(edges[x][e], x, edges[x][e]);
}

inline void node_update(int x) {
  nodes[x].answer = std::min(nodes[x << 1].answer, nodes[(x << 1) | 1].answer);
}

inline void node_pushdown(int x) {
  nodes[x << 1].lazy += nodes[x].lazy;
  nodes[(x << 1) | 1].lazy += nodes[x].lazy;
  nodes[(x << 1) | 1].answer.first += nodes[x].lazy;
  nodes[x << 1].answer.first += nodes[x].lazy;
  nodes[x].lazy = 0;
}

void tree_insert(int x, int l, int r) {
  if (ql > r || qr < l)
    return;
  if (ql <= l && r <= qr) {
    nodes[x].data.push_back(qx);
    ++nodes[x].lazy;
    ++nodes[x].answer.first;
    return;
  }
  node_pushdown(x);
  tree_insert(x << 1, l, (l + r) >> 1);
  tree_insert((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

void tree_remove(int x, int l, int r) {
  if (ql > r || qr < l)
    return;
  if (ql <= l && r <= qr) {
    --nodes[x].lazy;
    --nodes[x].answer.first;
    return;
  }
  node_pushdown(x);
  tree_remove(x << 1, l, (l + r) >> 1);
  tree_remove((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

int tree_get(int x, int l, int r) {
  int k;

  for (k = 0; k < nodes[x].data.size(); ++k)
    if (!removed[nodes[x].data[k]])
      break;
  if (k != nodes[x].data.size())
    k = nodes[x].data[0] = nodes[x].data[k], nodes[x].data.resize(1);
  else
    nodes[x].data.clear(), k = 0;

  if (l == r) {
    nodes[x].answer.first = 0x7f7f7f7f;
    return k;
  }

  node_pushdown(x);
  if (qx <= (l + r) >> 1)
    k += tree_get(x << 1, l, (l + r) >> 1);
  else
    k += tree_get((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
  return k;
}

void tree_build(int x, int l, int r) {
  if (l == r) {
    nodes[x].answer.second = l;
    return;
  }
  tree_build(x << 1, l, (l + r) >> 1);
  tree_build((x << 1) | 1, ((l + r) >> 1) + 1, r);
  node_update(x);
}

int lca(int x, int y) {
  while (top[x] != top[y])
    if (deep[top[x]] > deep[top[y]])
      x = father[top[x]];
    else
      y = father[top[y]];
  return deep[x] > deep[y] ? y : x;
}

void cover(int x, int y, bool z) {
  while (top[x] != top[y])
    ql = dfn[top[x]], qr = dfn[x], tree_insert(1, 2, n), x = father[top[x]];
  if (z || x != y)
    ql = dfn[y] + (z ? 0 : 1), qr = dfn[x], tree_insert(1, 2, n);
}

void uncover(int x, int y, bool z) {
  while (top[x] != top[y])
    ql = dfn[top[x]], qr = dfn[x], tree_remove(1, 2, n), x = father[top[x]];
  if (z || x != y)
    ql = dfn[y] + (z ? 0 : 1), qr = dfn[x], tree_remove(1, 2, n);
}

int main(void) {
  int i;
  int u, v, w;

  // freopen("x.in","r",stdin);

  scanf("%d", &n);
  for (i = 1; i <= n - 1; ++i)
    scanf("%d %d", &u, &v), edges[u].push_back(v), edges[v].push_back(u);

  dfs0(1, 0);
  dfs(1, 0, 1);
  tree_build(1, 2, n);

  for (i = 1; i <= n - 1; ++i) {
    scanf("%d %d", &u, &v);
    saved_edges[i].first = u;
    saved_edges[i].second = v;
    qx = i;
    w = lca(u, v);
    cover(u, w, 0);
    cover(v, w, 0);
  }

  for (i = 1; i <= n - 1; ++i) {
    if (nodes[1].answer.first != 1)
      return puts("NO"), 0;
    qx = nodes[1].answer.second;
    w = tree_get(1, 2, n);
    removed[w] = 1;
    u = saved_edges[w].first;
    v = saved_edges[w].second;
    w = lca(u, v);
    uncover(u, w, 0);
    uncover(v, w, 0);
  }
  puts("YES");

  return 0;
}