Problem p03235 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct Tree {
  int mx;
  int lch, rch;
} T[6400010];
int tot;
void update(int root) {
  int lc = T[root].lch;
  int rc = T[root].rch;
  T[root].mx = max(T[lc].mx, T[rc].mx);
  return;
}
void insert(int lstroot, int &nowroot, int l, int r, int x, int y) {
  nowroot = ++tot;
  if (l == r) {
    T[nowroot].mx = max(T[lstroot].mx, y);
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid) {
    T[nowroot].rch = T[lstroot].rch;
    insert(T[lstroot].lch, T[nowroot].lch, l, mid, x, y);
  } else {
    T[nowroot].lch = T[lstroot].lch;
    insert(T[lstroot].rch, T[nowroot].rch, mid + 1, r, x, y);
  }
  update(nowroot);
  return;
}
int query(int root, int l, int r, int x, int y) {
  if (x <= l && r <= y)
    return T[root].mx;
  int mid = (l + r) >> 1;
  if (x <= mid) {
    if (y > mid)
      return max(query(T[root].lch, l, mid, x, y),
                 query(T[root].rch, mid + 1, r, x, y));
    return query(T[root].lch, l, mid, x, y);
  }
  return query(T[root].rch, mid + 1, r, x, y);
}
int rt[200010][2];
int n, p[200010], c[200010], f[200010];
void init() {
  int mx = 0;
  for (int i = 1; i <= n; i++)
    if (p[i] > mx) {
      mx = p[i];
      c[i] = 2;
    } else
      c[i] = 1;
  for (int i = n; i >= 1; i--)
    f[i] = f[i + 1] + c[i] - 1;
  for (int i = n; i >= 1; i--)
    for (int j = 0; j < 2; j++) {
      rt[i][j] = rt[i + 1][j];
      int val = query(rt[i + 1][(j + c[i]) & 1], 1, n, p[i], n) + c[i];
      if (val % 2 == j) {
        //				printf("%d,%d:%d\n",i,j,val);
        insert(rt[i + 1][j], rt[i][j], 1, n, p[i], val);
      }
    }
  return;
}
bool check(int H1, int C1, int H2, int C2, int opt, int i) {
  if (opt == 0) {
    C1 += (p[i] > H1);
    H1 = max(H1, p[i]);
  } else {
    C2 += (p[i] > H2);
    H2 = max(H2, p[i]);
  }
  int need;
  // in 2
  need = C1 - C2 + f[i + 1];
  if (need >= 0 && query(rt[i + 1][need & 1], 1, n, H2, n) >= need)
    return true;
  // in 1
  need = C2 - C1 + f[i + 1];
  if (need >= 0 && query(rt[i + 1][need & 1], 1, n, H1, n) >= need)
    return true;
  return false;
}
char ans[200010];
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++)
    scanf("%d", &p[i]);
  init();
  int H1 = 0, C1 = 0, H2 = 0, C2 = 0;
  for (int i = 1; i <= n; i++) {
    if (check(H1, C1, H2, C2, 0, i)) {
      C1 += (p[i] > H1);
      H1 = max(H1, p[i]);
      ans[i] = '0';
    } else if (check(H1, C1, H2, C2, 1, i)) {
      C2 += (p[i] > H2);
      H2 = max(H2, p[i]);
      ans[i] = '1';
    } else {
      printf("-1\n");
      return 0;
    }
  }
  printf("%s\n", ans + 1);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct Tree {
  int mx;
  int lch, rch;
} T[12800010];
int tot;
void update(int root) {
  int lc = T[root].lch;
  int rc = T[root].rch;
  T[root].mx = max(T[lc].mx, T[rc].mx);
  return;
}
void insert(int lstroot, int &nowroot, int l, int r, int x, int y) {
  nowroot = ++tot;
  if (l == r) {
    T[nowroot].mx = max(T[lstroot].mx, y);
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid) {
    T[nowroot].rch = T[lstroot].rch;
    insert(T[lstroot].lch, T[nowroot].lch, l, mid, x, y);
  } else {
    T[nowroot].lch = T[lstroot].lch;
    insert(T[lstroot].rch, T[nowroot].rch, mid + 1, r, x, y);
  }
  update(nowroot);
  return;
}
int query(int root, int l, int r, int x, int y) {
  if (x <= l && r <= y)
    return T[root].mx;
  int mid = (l + r) >> 1;
  if (x <= mid) {
    if (y > mid)
      return max(query(T[root].lch, l, mid, x, y),
                 query(T[root].rch, mid + 1, r, x, y));
    return query(T[root].lch, l, mid, x, y);
  }
  return query(T[root].rch, mid + 1, r, x, y);
}
int rt[200010][2];
int n, p[200010], c[200010], f[200010];
void init() {
  int mx = 0;
  for (int i = 1; i <= n; i++)
    if (p[i] > mx) {
      mx = p[i];
      c[i] = 2;
    } else
      c[i] = 1;
  for (int i = n; i >= 1; i--)
    f[i] = f[i + 1] + c[i] - 1;
  for (int i = n; i >= 1; i--)
    for (int j = 0; j < 2; j++) {
      rt[i][j] = rt[i + 1][j];
      int val = query(rt[i + 1][(j + c[i]) & 1], 1, n, p[i], n) + c[i];
      if (val % 2 == j) {
        //				printf("%d,%d:%d\n",i,j,val);
        insert(rt[i + 1][j], rt[i][j], 1, n, p[i], val);
      }
    }
  return;
}
bool check(int H1, int C1, int H2, int C2, int opt, int i) {
  if (opt == 0) {
    C1 += (p[i] > H1);
    H1 = max(H1, p[i]);
  } else {
    C2 += (p[i] > H2);
    H2 = max(H2, p[i]);
  }
  int need;
  // in 2
  need = C1 - C2 + f[i + 1];
  if (need >= 0 && query(rt[i + 1][need & 1], 1, n, H2, n) >= need)
    return true;
  // in 1
  need = C2 - C1 + f[i + 1];
  if (need >= 0 && query(rt[i + 1][need & 1], 1, n, H1, n) >= need)
    return true;
  return false;
}
char ans[200010];
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++)
    scanf("%d", &p[i]);
  init();
  int H1 = 0, C1 = 0, H2 = 0, C2 = 0;
  for (int i = 1; i <= n; i++) {
    if (check(H1, C1, H2, C2, 0, i)) {
      C1 += (p[i] > H1);
      H1 = max(H1, p[i]);
      ans[i] = '0';
    } else if (check(H1, C1, H2, C2, 1, i)) {
      C2 += (p[i] > H2);
      H2 = max(H2, p[i]);
      ans[i] = '1';
    } else {
      printf("-1\n");
      return 0;
    }
  }
  printf("%s\n", ans + 1);
  return 0;
}