Problem p03235 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ph push
#define ptc putchar
#define enter putchar('\n')
#define mod 998244353
using namespace std;
typedef pair<int, int> pii;
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long lnt;
inline int read() {
  int x = 0;
  char c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c))
    x = (x << 1) + (x << 3) + c - '0', c = getchar();
  return x;
}
inline void write(int x) {
  if (!x) {
    ptc('0');
    return;
  }
  int dg[20], len = 0;
  while (x)
    dg[len++] = x % 10, x /= 10;
  while (len--)
    ptc(dg[len] + '0');
}
inline void writeln(int x) {
  write(x);
  ptc('\n');
}
inline int add(int x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
  return x;
}
inline int sub(int x, int y) {
  x -= y;
  if (x < 0)
    x += mod;
  return x;
}
inline int qpow(int x, int y) {
  int res = 1;
  while (y) {
    if (y & 1)
      res = 1ll * res * x % mod;
    x = 1ll * x * x % mod;
    y >>= 1;
  }
  return res;
}
const int N = 1e5 + 10;
int n, a[N], premax[N], sufsumpremaxcnt[N];

struct Node {
  int maxn, ls, rs;
} tr[N * 50];
int tcnt;

struct Segment_Tree {
  int rt[N];
  void up(int x) {
    if (!tr[x].ls)
      tr[x].maxn = tr[tr[x].rs].maxn;
    else if (!tr[x].rs)
      tr[x].maxn = tr[tr[x].ls].maxn;
    else
      tr[x].maxn = max(tr[tr[x].ls].maxn, tr[tr[x].rs].maxn);
  }
  void insert(int &x, int prex, int l, int r, int pos, int v) {
    x = ++tcnt;
    if (l == r) {
      tr[x].maxn = v;
      return;
    }
    int mid = l + r >> 1;
    if (pos <= mid) {
      tr[x].rs = tr[prex].rs;
      insert(tr[x].ls, tr[prex].ls, l, mid, pos, v);
    } else {
      tr[x].ls = tr[prex].ls;
      insert(tr[x].rs, tr[prex].rs, mid + 1, r, pos, v);
    }
    up(x);
  }

  int query(int x, int l, int r, int ql, int qr) {
    if (!x || ql > qr)
      return 0;
    if (ql <= l && r <= qr)
      return tr[x].maxn;
    int mid = l + r >> 1, res = 0;
    if (ql <= mid)
      res = max(res, query(tr[x].ls, l, mid, ql, qr));
    if (mid < qr)
      res = max(res, query(tr[x].rs, mid + 1, r, ql, qr));
    return res;
  }
} T[2];

int s[2][N], maxn[2][N], len[2], sum[2];

int res[N];

int check(int id, int pos) { //[pos , n]
  int need = sum[id] - sum[id ^ 1] + sufsumpremaxcnt[pos];
  if (need < 0)
    return 0;
  int most = T[need & 1].query(T[need & 1].rt[pos], 1, n,
                               maxn[id ^ 1][len[id ^ 1]] + 1, n);
  return most >= need;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", a + i);
    premax[i] = max(premax[i - 1], a[i]);
  }
  for (int i = n; i >= 1; i--) {
    sufsumpremaxcnt[i] = sufsumpremaxcnt[i + 1] + (premax[i] == a[i]);
  }

  for (int i = n; i >= 1; i--) {

    int d0max = T[0].query(T[0].rt[i + 1], 1, n, a[i] + 1, n),
        d1max = T[1].query(T[1].rt[i + 1], 1, n, a[i] + 1, n);
    if (premax[i] == a[i]) {
      T[0].insert(T[0].rt[i], T[0].rt[i + 1], 1, n, a[i], d0max + 2);
      if (d1max)
        T[1].insert(T[1].rt[i], T[1].rt[i + 1], 1, n, a[i], d1max + 2);
      else
        T[1].rt[i] = T[1].rt[i + 1];
    } else {
      T[1].insert(T[1].rt[i], T[1].rt[i + 1], 1, n, a[i], d0max + 1);
      if (d1max)
        T[0].insert(T[0].rt[i], T[0].rt[i + 1], 1, n, a[i], d1max + 1);
      else
        T[0].rt[i] = T[0].rt[i + 1];
    }
    /*
    printf("This is %d [%d %d]\n",i,d0max,d1max);
    printf("ou:\n");
    for (int j = 1;j <= n;j++) printf("%d
    ",T[0].query(T[0].rt[i],1,n,j,j));enter; printf("ji:\n"); for (int j = 1;j
    <= n;j++) printf("%d ",T[1].query(T[1].rt[i],1,n,j,j));enter;*/
  }
  memset(res, -1, sizeof res);

  for (int i = 1; i <= n; i++) {
    for (int d = 0; d < 2; d++) {
      s[d][++len[d]] = a[i];
      maxn[d][len[d]] = max(maxn[d][len[d] - 1], a[i]);
      sum[d] += maxn[d][len[d]] == s[d][len[d]];

      if (check(0, i + 1)) {
        res[i] = d;
        break;
      }
      if (check(1, i + 1)) {
        res[i] = d;
        break;
      }

      sum[d] -= maxn[d][len[d]] == s[d][len[d]];
      --len[d];
    }

    if (res[i] == -1)
      return puts("-1"), 0;
  }
  for (int i = 1; i <= n; i++)
    printf("%d", res[i]);
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ph push
#define ptc putchar
#define enter putchar('\n')
#define mod 998244353
using namespace std;
typedef pair<int, int> pii;
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long lnt;
inline int read() {
  int x = 0;
  char c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c))
    x = (x << 1) + (x << 3) + c - '0', c = getchar();
  return x;
}
inline void write(int x) {
  if (!x) {
    ptc('0');
    return;
  }
  int dg[20], len = 0;
  while (x)
    dg[len++] = x % 10, x /= 10;
  while (len--)
    ptc(dg[len] + '0');
}
inline void writeln(int x) {
  write(x);
  ptc('\n');
}
inline int add(int x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
  return x;
}
inline int sub(int x, int y) {
  x -= y;
  if (x < 0)
    x += mod;
  return x;
}
inline int qpow(int x, int y) {
  int res = 1;
  while (y) {
    if (y & 1)
      res = 1ll * res * x % mod;
    x = 1ll * x * x % mod;
    y >>= 1;
  }
  return res;
}
const int N = 2e5 + 10;
int n, a[N], premax[N], sufsumpremaxcnt[N];

struct Node {
  int maxn, ls, rs;
} tr[N * 50];
int tcnt;

struct Segment_Tree {
  int rt[N];
  void up(int x) {
    if (!tr[x].ls)
      tr[x].maxn = tr[tr[x].rs].maxn;
    else if (!tr[x].rs)
      tr[x].maxn = tr[tr[x].ls].maxn;
    else
      tr[x].maxn = max(tr[tr[x].ls].maxn, tr[tr[x].rs].maxn);
  }
  void insert(int &x, int prex, int l, int r, int pos, int v) {
    x = ++tcnt;
    if (l == r) {
      tr[x].maxn = v;
      return;
    }
    int mid = l + r >> 1;
    if (pos <= mid) {
      tr[x].rs = tr[prex].rs;
      insert(tr[x].ls, tr[prex].ls, l, mid, pos, v);
    } else {
      tr[x].ls = tr[prex].ls;
      insert(tr[x].rs, tr[prex].rs, mid + 1, r, pos, v);
    }
    up(x);
  }

  int query(int x, int l, int r, int ql, int qr) {
    if (!x || ql > qr)
      return 0;
    if (ql <= l && r <= qr)
      return tr[x].maxn;
    int mid = l + r >> 1, res = 0;
    if (ql <= mid)
      res = max(res, query(tr[x].ls, l, mid, ql, qr));
    if (mid < qr)
      res = max(res, query(tr[x].rs, mid + 1, r, ql, qr));
    return res;
  }
} T[2];

int s[2][N], maxn[2][N], len[2], sum[2];

int res[N];

int check(int id, int pos) { //[pos , n]
  int need = sum[id] - sum[id ^ 1] + sufsumpremaxcnt[pos];
  if (need < 0)
    return 0;
  int most = T[need & 1].query(T[need & 1].rt[pos], 1, n,
                               maxn[id ^ 1][len[id ^ 1]] + 1, n);
  return most >= need;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", a + i);
    premax[i] = max(premax[i - 1], a[i]);
  }
  for (int i = n; i >= 1; i--) {
    sufsumpremaxcnt[i] = sufsumpremaxcnt[i + 1] + (premax[i] == a[i]);
  }

  for (int i = n; i >= 1; i--) {

    int d0max = T[0].query(T[0].rt[i + 1], 1, n, a[i] + 1, n),
        d1max = T[1].query(T[1].rt[i + 1], 1, n, a[i] + 1, n);
    if (premax[i] == a[i]) {
      T[0].insert(T[0].rt[i], T[0].rt[i + 1], 1, n, a[i], d0max + 2);
      if (d1max)
        T[1].insert(T[1].rt[i], T[1].rt[i + 1], 1, n, a[i], d1max + 2);
      else
        T[1].rt[i] = T[1].rt[i + 1];
    } else {
      T[1].insert(T[1].rt[i], T[1].rt[i + 1], 1, n, a[i], d0max + 1);
      if (d1max)
        T[0].insert(T[0].rt[i], T[0].rt[i + 1], 1, n, a[i], d1max + 1);
      else
        T[0].rt[i] = T[0].rt[i + 1];
    }
    /*
    printf("This is %d [%d %d]\n",i,d0max,d1max);
    printf("ou:\n");
    for (int j = 1;j <= n;j++) printf("%d
    ",T[0].query(T[0].rt[i],1,n,j,j));enter; printf("ji:\n"); for (int j = 1;j
    <= n;j++) printf("%d ",T[1].query(T[1].rt[i],1,n,j,j));enter;*/
  }
  memset(res, -1, sizeof res);

  for (int i = 1; i <= n; i++) {
    for (int d = 0; d < 2; d++) {
      s[d][++len[d]] = a[i];
      maxn[d][len[d]] = max(maxn[d][len[d] - 1], a[i]);
      sum[d] += maxn[d][len[d]] == s[d][len[d]];

      if (check(0, i + 1)) {
        res[i] = d;
        break;
      }
      if (check(1, i + 1)) {
        res[i] = d;
        break;
      }

      sum[d] -= maxn[d][len[d]] == s[d][len[d]];
      --len[d];
    }

    if (res[i] == -1)
      return puts("-1"), 0;
  }
  for (int i = 1; i <= n; i++)
    printf("%d", res[i]);
  return 0;
}