Problem p03727 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 11451411
#define MOD 1000000007
struct HLDecomposition {
  int N;
  vector<vector<int>> G;
  vector<int> next, par, head, tid, rev;
  HLDecomposition(int N)
      : N(N), G(N), next(N, -1), par(N, -1), head(N, -1), tid(N, -1),
        rev(N, -1) {}
  void add_edge(int x, int y) {
    G[x].pb(y);
    G[y].pb(x);
  }
  int dfs(int x, int p) {
    par[x] = p;
    int sz = 1, cur = 0;
    for (int t : G[x])
      if (t != p) {
        int c = dfs(t, x);
        sz += c;
        if (cur < c)
          cur = c, next[x] = t;
      }
    return sz;
  }
  void build() {
    assert(dfs(0, -1) == N);
    bfs(0);
  }
  void bfs(int s) {
    int k = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
      int h = q.front();
      q.pop();
      for (int x = h; x != -1; x = next[x]) {
        head[x] = h, rev[k] = x, tid[x] = k++;
        for (int t : G[x])
          if (t != par[x] && t != next[x])
            q.push(t);
      }
      // for (int x=h; x!=-1; x=next[x]) for (int t : G[x]) if (tid[t] == -1)
      // q.push(t);
    }
    assert(k == N);
  }
  void for_each(int u, int v, function<void(int, int)> f) {
    if (u == v)
      return;
    if (tid[u] > tid[v])
      swap(u, v);
    if (head[u] == head[v])
      return f(tid[u] + 1, tid[v]);
    if (tid[head[u]] > tid[head[v]])
      swap(u, v);
    f(tid[head[v]], tid[v]);
    for_each(u, par[head[v]], f);
  }
};

bool used[100000];
#define MAX_N (1 << 17)
struct SegTree {
  vector<int> seg[MAX_N * 2 - 1];
  void add(int a, int b, int x, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b) {
      seg[k].pb(x);
      return;
    }
    add(a, b, x, k * 2 + 1, l, (l + r) / 2);
    add(a, b, x, k * 2 + 2, (l + r) / 2, r);
  }
  int query(int a, int b, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return -1;
    while (!seg[k].empty() && used[seg[k].back()])
      seg[k].pop_back();
    if (!seg[k].empty())
      return *seg[k].begin();
    if (a <= l && r <= b)
      return -1;
    return max(query(a, b, k * 2 + 1, l, (l + r) / 2),
               query(a, b, k * 2 + 2, (l + r) / 2, r));
  }
};

struct SegTree2 {
  P seg[MAX_N * 2 - 1] = {};
  int lazy[MAX_N * 2 - 1] = {};
  SegTree2(int N) {
    rep(i, MAX_N * 2 - 1) seg[i] = P(2, -1);
    rep(i, N) seg[i + MAX_N - 1] = P(0, i);
    for (int i = MAX_N - 2; i >= 0; i--)
      seg[i] = min(seg[i * 2 + 1], seg[i * 2 + 2]);
  }
  void setLazy(int k, int v) {
    seg[k]._1 += v;
    lazy[k] += v;
  }
  void push(int k) {
    if (lazy[k] == 0)
      return;
    setLazy(k * 2 + 1, lazy[k]);
    setLazy(k * 2 + 2, lazy[k]);
    lazy[k] = 0;
  }
  void add(int a, int b, int val, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b)
      return setLazy(k, val);
    push(k);
    add(a, b, val, k * 2 + 1, l, (l + r) / 2);
    add(a, b, val, k * 2 + 2, (l + r) / 2, r);
    seg[k] = min(seg[k * 2 + 1], seg[k * 2 + 2]);
  }
  P query(int a, int b, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return P(2, -1);
    if (a <= l && r <= b)
      return seg[k];
    push(k);
    return min(query(a, b, k * 2 + 1, l, (l + r) / 2),
               query(a, b, k * 2 + 2, (l + r) / 2, r));
  }
};

int N;
vector<int> G[100000];
int C[100000], D[100000];
SegTree seg;

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  SegTree2 seg2(N);
  HLDecomposition hld(N);
  rep(i, N - 1) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    hld.add_edge(a, b);
  }
  hld.build();
  seg2.add(hld.tid[0], hld.tid[0] + 1, 2);

  rep(i, N - 1) {
    cin >> C[i] >> D[i];
    C[i]--, D[i]--;
    hld.for_each(C[i], D[i], [&](int l, int r) {
      seg.add(l, r + 1, i);
      seg2.add(l, r + 1, 1);
    });
  }
  rep(_, N - 1) {
    if (seg2.seg[0]._1 != 1) {
      cout << "NO\n";
      return 0;
    }
    int pos = seg2.seg[0]._2;
    int id = seg.query(pos, pos + 1);
    assert(id != -1);
    seg2.add(pos, pos + 1, 2); // +INF
    used[id] = true;
    hld.for_each(C[id], D[id], [&](int l, int r) { seg2.add(l, r + 1, -1); });
  }
  cout << "YES\n";
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 11451411
#define MOD 1000000007
struct HLDecomposition {
  int N;
  vector<vector<int>> G;
  vector<int> next, par, head, tid, rev;
  HLDecomposition(int N)
      : N(N), G(N), next(N, -1), par(N, -1), head(N, -1), tid(N, -1),
        rev(N, -1) {}
  void add_edge(int x, int y) {
    G[x].pb(y);
    G[y].pb(x);
  }
  int dfs(int x, int p) {
    par[x] = p;
    int sz = 1, cur = 0;
    for (int t : G[x])
      if (t != p) {
        int c = dfs(t, x);
        sz += c;
        if (cur < c)
          cur = c, next[x] = t;
      }
    return sz;
  }
  void build() {
    assert(dfs(0, -1) == N);
    bfs(0);
  }
  void bfs(int s) {
    int k = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
      int h = q.front();
      q.pop();
      for (int x = h; x != -1; x = next[x]) {
        head[x] = h, rev[k] = x, tid[x] = k++;
        for (int t : G[x])
          if (t != par[x] && t != next[x])
            q.push(t);
      }
      // for (int x=h; x!=-1; x=next[x]) for (int t : G[x]) if (tid[t] == -1)
      // q.push(t);
    }
    assert(k == N);
  }
  void for_each(int u, int v, function<void(int, int)> f) {
    if (u == v)
      return;
    if (tid[u] > tid[v])
      swap(u, v);
    if (head[u] == head[v])
      return f(tid[u] + 1, tid[v]);
    if (tid[head[u]] > tid[head[v]])
      swap(u, v);
    f(tid[head[v]], tid[v]);
    for_each(u, par[head[v]], f);
  }
};

bool used[100000];
#define MAX_N (1 << 17)
struct SegTree {
  vector<int> seg[MAX_N * 2 - 1];
  void add(int a, int b, int x, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b) {
      seg[k].pb(x);
      return;
    }
    add(a, b, x, k * 2 + 1, l, (l + r) / 2);
    add(a, b, x, k * 2 + 2, (l + r) / 2, r);
  }
  int query(int a, int b, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return -1;
    while (!seg[k].empty() && used[seg[k].back()])
      seg[k].pop_back();
    if (!seg[k].empty())
      return seg[k].back();
    if (a <= l && r <= b)
      return -1;
    return max(query(a, b, k * 2 + 1, l, (l + r) / 2),
               query(a, b, k * 2 + 2, (l + r) / 2, r));
  }
};

struct SegTree2 {
  P seg[MAX_N * 2 - 1] = {};
  int lazy[MAX_N * 2 - 1] = {};
  SegTree2(int N) {
    rep(i, MAX_N * 2 - 1) seg[i] = P(2, -1);
    rep(i, N) seg[i + MAX_N - 1] = P(0, i);
    for (int i = MAX_N - 2; i >= 0; i--)
      seg[i] = min(seg[i * 2 + 1], seg[i * 2 + 2]);
  }
  void setLazy(int k, int v) {
    seg[k]._1 += v;
    lazy[k] += v;
  }
  void push(int k) {
    if (lazy[k] == 0)
      return;
    setLazy(k * 2 + 1, lazy[k]);
    setLazy(k * 2 + 2, lazy[k]);
    lazy[k] = 0;
  }
  void add(int a, int b, int val, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b)
      return setLazy(k, val);
    push(k);
    add(a, b, val, k * 2 + 1, l, (l + r) / 2);
    add(a, b, val, k * 2 + 2, (l + r) / 2, r);
    seg[k] = min(seg[k * 2 + 1], seg[k * 2 + 2]);
  }
  P query(int a, int b, int k = 0, int l = 0, int r = MAX_N) {
    if (b <= l || r <= a)
      return P(2, -1);
    if (a <= l && r <= b)
      return seg[k];
    push(k);
    return min(query(a, b, k * 2 + 1, l, (l + r) / 2),
               query(a, b, k * 2 + 2, (l + r) / 2, r));
  }
};

int N;
vector<int> G[100000];
int C[100000], D[100000];
SegTree seg;

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  SegTree2 seg2(N);
  HLDecomposition hld(N);
  rep(i, N - 1) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    hld.add_edge(a, b);
  }
  hld.build();
  seg2.add(hld.tid[0], hld.tid[0] + 1, 2);

  rep(i, N - 1) {
    cin >> C[i] >> D[i];
    C[i]--, D[i]--;
    hld.for_each(C[i], D[i], [&](int l, int r) {
      seg.add(l, r + 1, i);
      seg2.add(l, r + 1, 1);
    });
  }
  rep(_, N - 1) {
    if (seg2.seg[0]._1 != 1) {
      cout << "NO\n";
      return 0;
    }
    int pos = seg2.seg[0]._2;
    int id = seg.query(pos, pos + 1);
    assert(id != -1);
    seg2.add(pos, pos + 1, 2); // +INF
    used[id] = true;
    hld.for_each(C[id], D[id], [&](int l, int r) { seg2.add(l, r + 1, -1); });
  }
  cout << "YES\n";
  return 0;
}