Problem p03727 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-')
      f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}

const int N = 100005;
int n;
int to[N * 2], nxt[N * 2], head[N], cnt;
struct edge {
  int x, y;
} e[N];
int top[N], size[N], dfn[N], DFN, son[N], f[N];
int tot, dep[N];
bool vis[N];
queue<int> Q;
int Head[N << 2], Cnt, Nxt[N << 6], To[N << 6];
int sum[N << 2], lazy[N << 2];

void dfs(int x, int fa) {
  size[x] = 1;
  f[x] = fa;
  dep[x] = dep[fa] + 1;
  for (int i = head[x]; i; i = nxt[i])
    if (to[i] != fa) {
      dfs(to[i], x);
      size[x] += size[to[i]];
      if (size[to[i]] > size[son[x]])
        son[x] = to[i];
    }
}
void dfs2(int x, int fa) {
  dfn[x] = ++DFN;
  top[x] = fa;
  if (son[x] != 0)
    dfs2(son[x], fa);
  for (int i = head[x]; i; i = nxt[i])
    if (to[i] != f[x] && to[i] != son[x])
      dfs2(to[i], to[i]);
}

inline void insert(int x, int y) {
  to[++cnt] = y;
  nxt[cnt] = head[x];
  head[x] = cnt;
}
inline void Insert(int x, int y) {
  To[++Cnt] = y;
  Nxt[Cnt] = Head[x];
  Head[x] = Cnt;
}

void modify(int num, int l, int r, int x, int y, int p) {
  if (x <= l && r <= y) {
    Insert(num, p);
    sum[num]++;
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid)
    modify(num << 1, l, mid, x, y, p);
  if (y > mid)
    modify(num << 1 | 1, mid + 1, r, x, y, p);
}

void addsum(int x, int y, int p) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]])
      swap(x, y);
    modify(1, 2, n, dfn[top[x]], dfn[x], p);
    x = f[top[x]];
  }
  if (dep[x] < dep[y])
    swap(x, y);
  if (x != y)
    modify(1, 2, n, dfn[y] + 1, dfn[x], p);
}

inline void down(int k) {
  int l = k << 1, r = k << 1 | 1;
  sum[l] += sum[k];
  sum[r] += sum[k];
  sum[k] = 0;
}

void Getpos(int num, int l, int r) {
  if (l == r) {
    if (sum[num] == 0)
      sum[num] = 1e9;
    if (sum[num] == 1)
      Q.push(l), sum[num] = 1e9;
    return;
  }
  down(num);
  int mid = (l + r) >> 1;
  Getpos(num << 1, l, mid);
  Getpos(num << 1 | 1, mid + 1, r);
  sum[num] = min(sum[num << 1], sum[num << 1 | 1]);
}

int check(int num, int l, int r, int x) {
  for (int i = Head[num]; i; i = Nxt[i]) {
    //		printf("%d %d %d %d\n",WE[num][i],l,r,x);
    if (!vis[To[i]]) {
      Head[num] = Nxt[i];
      return To[i];
    }
  }
  if (l == r)
    return 0;
  int mid = (l + r) >> 1;
  if (x <= mid)
    return check(num << 1, l, mid, x);
  else
    return check(num << 1 | 1, mid + 1, r, x);
}

void Down(int k) {
  int l = k << 1, r = k << 1 | 1;
  sum[l] -= lazy[k];
  sum[r] -= lazy[k];
  lazy[l] += lazy[k];
  lazy[r] += lazy[k];
  lazy[k] = 0;
}

void delchange(int num, int l, int r, int x, int y) {
  if (x <= l && r <= y && sum[num] > 2) {
    sum[num] -= 1;
    lazy[num] += 1;
    return;
  }
  if (l == r) {
    sum[num]--;
    if (sum[num] == 1)
      Q.push(l), sum[num] = 1e9;
    else if (sum[num] == 0)
      sum[num] = 1e9;
    return;
  }
  Down(num);
  int mid = (l + r) >> 1;
  if (x <= mid)
    delchange(num << 1, l, mid, x, y);
  if (y > mid)
    delchange(num << 1 | 1, mid + 1, r, x, y);
  sum[num] = min(sum[num << 1], sum[num << 1 | 1]);
}

void del(int x, int y, int p) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]])
      swap(x, y);
    delchange(1, 2, n, dfn[top[x]], dfn[x]);
    x = f[top[x]];
  }
  if (dep[x] < dep[y])
    swap(x, y);
  if (x != y)
    delchange(1, 2, n, dfn[y] + 1, dfn[x]);
}

signed main() {
  n = read();
  for (int i = 1; i < n; ++i) {
    int a = read(), b = read();
    insert(a, b);
    insert(b, a);
  }
  for (int i = 1; i < n; ++i) {
    e[i].x = read();
    e[i].y = read();
  }
  dfs(1, 1);
  dfs2(1, 1);
  for (int i = 1; i < n; ++i)
    addsum(e[i].x, e[i].y, i);
  Getpos(1, 2, n);
  while (!Q.empty()) {
    int x = Q.front();
    Q.pop();
    int p = check(1, 2, n, x);
    if (p > 0) {
      ++tot;
      vis[p] = true;
      del(e[p].x, e[p].y, p);
    }
  }
  if (tot != n - 1)
    puts("NO");
  else
    puts("YES");
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-')
      f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}

const int N = 100005;
int n;
int to[N * 2], nxt[N * 2], head[N], cnt;
struct edge {
  int x, y;
} e[N];
int top[N], size[N], dfn[N], DFN, son[N], f[N];
int tot, dep[N];
bool vis[N];
queue<int> Q;
int Head[N << 2], Cnt, Nxt[N << 6], To[N << 6];
int sum[N << 2], lazy[N << 2];

void dfs(int x, int fa) {
  size[x] = 1;
  f[x] = fa;
  dep[x] = dep[fa] + 1;
  for (int i = head[x]; i; i = nxt[i])
    if (to[i] != fa) {
      dfs(to[i], x);
      size[x] += size[to[i]];
      if (size[to[i]] > size[son[x]])
        son[x] = to[i];
    }
}
void dfs2(int x, int fa) {
  dfn[x] = ++DFN;
  top[x] = fa;
  if (son[x] != 0)
    dfs2(son[x], fa);
  for (int i = head[x]; i; i = nxt[i])
    if (to[i] != f[x] && to[i] != son[x])
      dfs2(to[i], to[i]);
}

inline void insert(int x, int y) {
  to[++cnt] = y;
  nxt[cnt] = head[x];
  head[x] = cnt;
}
inline void Insert(int x, int y) {
  To[++Cnt] = y;
  Nxt[Cnt] = Head[x];
  Head[x] = Cnt;
}

void modify(int num, int l, int r, int x, int y, int p) {
  if (x <= l && r <= y) {
    Insert(num, p);
    sum[num]++;
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid)
    modify(num << 1, l, mid, x, y, p);
  if (y > mid)
    modify(num << 1 | 1, mid + 1, r, x, y, p);
}

void addsum(int x, int y, int p) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]])
      swap(x, y);
    modify(1, 2, n, dfn[top[x]], dfn[x], p);
    x = f[top[x]];
  }
  if (dep[x] < dep[y])
    swap(x, y);
  if (x != y)
    modify(1, 2, n, dfn[y] + 1, dfn[x], p);
}

inline void down(int k) {
  int l = k << 1, r = k << 1 | 1;
  sum[l] += sum[k];
  sum[r] += sum[k];
  sum[k] = 0;
}

void Getpos(int num, int l, int r) {
  if (l == r) {
    if (sum[num] == 0)
      sum[num] = 1e9;
    if (sum[num] == 1)
      Q.push(l), sum[num] = 1e9;
    return;
  }
  down(num);
  int mid = (l + r) >> 1;
  Getpos(num << 1, l, mid);
  Getpos(num << 1 | 1, mid + 1, r);
  sum[num] = min(sum[num << 1], sum[num << 1 | 1]);
}

int check(int num, int l, int r, int x) {
  for (int i = Head[num]; i; i = Nxt[i]) {
    //		printf("%d %d %d %d\n",WE[num][i],l,r,x);
    if (!vis[To[i]]) {
      Head[num] = Nxt[i];
      return To[i];
    }
  }
  Head[num] = 0;
  if (l == r)
    return 0;
  int mid = (l + r) >> 1;
  if (x <= mid)
    return check(num << 1, l, mid, x);
  else
    return check(num << 1 | 1, mid + 1, r, x);
}

void Down(int k) {
  int l = k << 1, r = k << 1 | 1;
  sum[l] -= lazy[k];
  sum[r] -= lazy[k];
  lazy[l] += lazy[k];
  lazy[r] += lazy[k];
  lazy[k] = 0;
}

void delchange(int num, int l, int r, int x, int y) {
  if (x <= l && r <= y && sum[num] > 2) {
    sum[num] -= 1;
    lazy[num] += 1;
    return;
  }
  if (l == r) {
    sum[num]--;
    if (sum[num] == 1)
      Q.push(l), sum[num] = 1e9;
    else if (sum[num] == 0)
      sum[num] = 1e9;
    return;
  }
  Down(num);
  int mid = (l + r) >> 1;
  if (x <= mid)
    delchange(num << 1, l, mid, x, y);
  if (y > mid)
    delchange(num << 1 | 1, mid + 1, r, x, y);
  sum[num] = min(sum[num << 1], sum[num << 1 | 1]);
}

void del(int x, int y, int p) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]])
      swap(x, y);
    delchange(1, 2, n, dfn[top[x]], dfn[x]);
    x = f[top[x]];
  }
  if (dep[x] < dep[y])
    swap(x, y);
  if (x != y)
    delchange(1, 2, n, dfn[y] + 1, dfn[x]);
}

signed main() {
  n = read();
  for (int i = 1; i < n; ++i) {
    int a = read(), b = read();
    insert(a, b);
    insert(b, a);
  }
  for (int i = 1; i < n; ++i) {
    e[i].x = read();
    e[i].y = read();
  }
  dfs(1, 1);
  dfs2(1, 1);
  for (int i = 1; i < n; ++i)
    addsum(e[i].x, e[i].y, i);
  Getpos(1, 2, n);
  while (!Q.empty()) {
    int x = Q.front();
    Q.pop();
    int p = check(1, 2, n, x);
    if (p > 0) {
      ++tot;
      vis[p] = true;
      del(e[p].x, e[p].y, p);
    }
  }
  if (tot != n - 1)
    puts("NO");
  else
    puts("YES");
  return 0;
}