Problem p03235 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 200100;
struct Node {
  int mx[2];
  Node *lch, *rch;
  Node() : mx(), lch(0), rch(0) {}
} node[maxn * 20];
typedef Node *pnode;
int tot = 0;
pnode root[maxn];
void update(pnode r) {
  r->mx[0] = max(r->lch->mx[0], r->rch->mx[0]);
  r->mx[1] = max(r->lch->mx[1], r->rch->mx[1]);
}
void build(pnode &r, int st, int ed) {
  r = &node[++tot];
  if (st == ed)
    return;
  int mid = (st + ed) >> 1;
  build(r->lch, st, mid);
  build(r->rch, mid + 1, ed);
}
int ask(pnode r, int ll, int rr, int asd, int st, int ed) {
  if (ll > rr)
    return 0;
  if (ll == st && rr == ed)
    return r->mx[asd];
  int ans = 0;
  int mid = (st + ed) >> 1;
  if (ll <= mid)
    ans = max(ans, ask(r->lch, ll, min(mid, rr), asd, st, mid));
  if (mid < rr)
    ans = max(ans, ask(r->rch, max(ll, mid + 1), rr, asd, mid + 1, ed));
  return ans;
}
void change(pnode &r, pnode nxt, int x, int y, int st, int ed) {
  r = &node[++tot];
  *r = *nxt;
  if (st == ed) {
    r->mx[y & 1] = max(r->mx[y & 1], y);
    return;
  }
  int mid = (st + ed) >> 1;
  if (x <= mid) {
    r->lch = 0;
    change(r->lch, nxt->lch, x, y, st, mid);
  } else {
    r->rch = 0;
    change(r->rch, nxt->rch, x, y, mid + 1, ed);
  }
  update(r);
}
void out(pnode r, int st, int ed) {
  cout << st << " " << ed << " " << r->mx[0] << " " << r->mx[1] << endl;
  if (st == ed)
    return;
  int mid = (st + ed) >> 1;
  out(r->lch, st, mid);
  out(r->rch, mid + 1, ed);
}
int p[maxn], v[maxn], num[maxn];
int n;
int main() {
  std::ios::sync_with_stdio(false);
  cin >> n;
  int mx = -1;
  num[0] = 0;
  for (int i = 1; i <= n; i++) {
    cin >> p[i];
    if (p[i] > mx) {
      v[i] = 2;
      mx = p[i];
    } else
      v[i] = 1;
    num[i] = num[i - 1] + v[i] - 1;
  }
  build(root[n + 1], 1, n);
  for (int i = n; i >= 1; i--) {
    // cerr << i << " ---------------------- " << endl;
    int a = ask(root[i + 1], p[i] + 1, n, 0, 1, n);
    int b = ask(root[i + 1], p[i] + 1, n, 1, 1, n);
    // cout << a << " " << b << endl;
    // cout << a + v[i] << " " << b + v[i] << endl;
    change(root[i], root[i + 1], p[i], a + v[i], 1, n);
    change(root[i], root[i], p[i], b + v[i], 1, n);
    // out(root[i], 1, n);
  }
  string s = "";
  int c1 = 0, c2 = 0, mx1 = 0, mx2 = 0;
  // cout << num[n] << endl;
  // cout << ask(root[1], mx2 + 1, n, num[n] & 1, 1, n) << " " << ask(root[1],
  // mx1 + 1, n, num[n] & 1, 1, n) << endl;
  if (ask(root[1], mx2 + 1, n, num[n] & 1, 1, n) < c1 - c2 + num[n] &&
      ask(root[1], mx1 + 1, n, num[n] & 1, 1, n) < c2 - c1 + num[n]) {
    cout << -1 << endl;
    return 0;
  }
  for (int i = 1; i <= n; i++) {
    // cerr << i << " ----------- " << endl;
    int a = num[n] - num[i];
    int nxt1 = mx1, nxtc = c1;
    if (p[i] > mx1) {
      mx1 = p[i];
      c1++;
    }
    int asd = (c1 - c2 + a) & 1;
    // cout << c1 << " " << mx1 << " " << c2 << " " << mx2 << " " << a << " " <<
    // c1 - c2 + a << " " << asd << endl; out(root[i + 1], 1, n); cout <<
    // ask(root[i + 1], mx2 + 1, n, asd, 1, n) << " " << ask(root[i + 1], mx1 +
    // 1, n, asd, 1, n) << endl;
    if ((c1 - c2 + a >= 0 &&
         ask(root[i + 1], mx2 + 1, n, asd, 1, n) >= c1 - c2 + a) ||
        (c2 - c1 + a >= 0 &&
         ask(root[i + 1], mx1 + 1, n, asd, 1, n) >= c2 - c1 + a))
      s += '0';
    else {
      mx1 = nxt1;
      c1 = nxtc;
      if (p[i] > mx2) {
        mx2 = p[i];
        c2++;
      }
      s += '1';
    }
  }
  cout << s << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 200100;
struct Node {
  int mx[2];
  Node *lch, *rch;
  Node() : mx(), lch(0), rch(0) {}
} node[maxn * 41];
typedef Node *pnode;
int tot = 0;
pnode root[maxn];
void update(pnode r) {
  r->mx[0] = max(r->lch->mx[0], r->rch->mx[0]);
  r->mx[1] = max(r->lch->mx[1], r->rch->mx[1]);
}
void build(pnode &r, int st, int ed) {
  r = &node[++tot];
  if (st == ed)
    return;
  int mid = (st + ed) >> 1;
  build(r->lch, st, mid);
  build(r->rch, mid + 1, ed);
}
int ask(pnode r, int ll, int rr, int asd, int st, int ed) {
  if (ll > rr)
    return 0;
  if (ll == st && rr == ed)
    return r->mx[asd];
  int ans = 0;
  int mid = (st + ed) >> 1;
  if (ll <= mid)
    ans = max(ans, ask(r->lch, ll, min(mid, rr), asd, st, mid));
  if (mid < rr)
    ans = max(ans, ask(r->rch, max(ll, mid + 1), rr, asd, mid + 1, ed));
  return ans;
}
void change(pnode &r, pnode nxt, int x, int y, int st, int ed) {
  r = &node[++tot];
  *r = *nxt;
  if (st == ed) {
    r->mx[y & 1] = max(r->mx[y & 1], y);
    return;
  }
  int mid = (st + ed) >> 1;
  if (x <= mid) {
    r->lch = 0;
    change(r->lch, nxt->lch, x, y, st, mid);
  } else {
    r->rch = 0;
    change(r->rch, nxt->rch, x, y, mid + 1, ed);
  }
  update(r);
}
void out(pnode r, int st, int ed) {
  cout << st << " " << ed << " " << r->mx[0] << " " << r->mx[1] << endl;
  if (st == ed)
    return;
  int mid = (st + ed) >> 1;
  out(r->lch, st, mid);
  out(r->rch, mid + 1, ed);
}
int p[maxn], v[maxn], num[maxn];
int n;
int main() {
  std::ios::sync_with_stdio(false);
  cin >> n;
  int mx = -1;
  num[0] = 0;
  for (int i = 1; i <= n; i++) {
    cin >> p[i];
    if (p[i] > mx) {
      v[i] = 2;
      mx = p[i];
    } else
      v[i] = 1;
    num[i] = num[i - 1] + v[i] - 1;
  }
  build(root[n + 1], 1, n);
  for (int i = n; i >= 1; i--) {
    // cerr << i << " ---------------------- " << endl;
    int a = ask(root[i + 1], p[i] + 1, n, 0, 1, n);
    int b = ask(root[i + 1], p[i] + 1, n, 1, 1, n);
    // cout << a << " " << b << endl;
    // cout << a + v[i] << " " << b + v[i] << endl;
    change(root[i], root[i + 1], p[i], a + v[i], 1, n);
    change(root[i], root[i], p[i], b + v[i], 1, n);
    // out(root[i], 1, n);
  }
  string s = "";
  int c1 = 0, c2 = 0, mx1 = 0, mx2 = 0;
  // cout << num[n] << endl;
  // cout << ask(root[1], mx2 + 1, n, num[n] & 1, 1, n) << " " << ask(root[1],
  // mx1 + 1, n, num[n] & 1, 1, n) << endl;
  if (ask(root[1], mx2 + 1, n, num[n] & 1, 1, n) < c1 - c2 + num[n] &&
      ask(root[1], mx1 + 1, n, num[n] & 1, 1, n) < c2 - c1 + num[n]) {
    cout << -1 << endl;
    return 0;
  }
  for (int i = 1; i <= n; i++) {
    // cerr << i << " ----------- " << endl;
    int a = num[n] - num[i];
    int nxt1 = mx1, nxtc = c1;
    if (p[i] > mx1) {
      mx1 = p[i];
      c1++;
    }
    int asd = (c1 - c2 + a) & 1;
    // cout << c1 << " " << mx1 << " " << c2 << " " << mx2 << " " << a << " " <<
    // c1 - c2 + a << " " << asd << endl; out(root[i + 1], 1, n); cout <<
    // ask(root[i + 1], mx2 + 1, n, asd, 1, n) << " " << ask(root[i + 1], mx1 +
    // 1, n, asd, 1, n) << endl;
    if ((c1 - c2 + a >= 0 &&
         ask(root[i + 1], mx2 + 1, n, asd, 1, n) >= c1 - c2 + a) ||
        (c2 - c1 + a >= 0 &&
         ask(root[i + 1], mx1 + 1, n, asd, 1, n) >= c2 - c1 + a))
      s += '0';
    else {
      mx1 = nxt1;
      c1 = nxtc;
      if (p[i] > mx2) {
        mx2 = p[i];
        c2++;
      }
      s += '1';
    }
  }
  cout << s << endl;
  return 0;
}