Problem p03641 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define PB push_back
using namespace std;
typedef pair<int, int> P1;
typedef pair<int, pair<int, int>> P2;
static const int INF = 1ll << 60;
static const int dx[] = {
    1,
    -1,
    0,
    0,
};
static const int dy[] = {0, 0, 1, -1};
P1 dat[2][400005];

class Segment {
public:
  int n;
  int ed;
  void init(int n_, int ed_) {
    n = 1;
    ed = ed_;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; ++i)
      dat[ed][i] = P1(INF, INF);
  }

  P1 Min(P1 a, P1 b) {
    if (a.first <= b.first)
      return a;
    else
      return b;
  }

  void update(int k, P1 a) {
    k += n - 1;
    dat[ed][k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[ed][k] = Min(dat[ed][k * 2 + 1], dat[ed][k * 2 + 2]);
    }
  }

  P1 query(int a, int b, int k, int l, int r) {
    if (a <= l && r <= b)
      return dat[ed][k];
    if (r <= a || b <= l)
      return P1(INF, INF);
    else {
      P1 vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      P1 vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return Min(vl, vr);
    }
  }
};

int N;
vector<int> p, q;
vector<P1> interval;
priority_queue<P2, vector<P2>, greater<P2>> minInterval;
Segment seg[2];

void divideInterval(P1 id, int i, int j) {
  P1 tmp = id;
  minInterval.push(P2(
      seg[tmp.first % 2].query(tmp.first, i, 0, 0, seg[tmp.first % 2].n).first,
      P1(tmp.first, i)));
  minInterval.push(
      P2(seg[(i + 1) % 2].query(i + 1, j, 0, 0, seg[(i + 1) % 2].n).first,
         P1(i + 1, j)));
  minInterval.push(P2(
      seg[(j + 1) % 2].query(j + 1, tmp.second, 0, 0, seg[(j + 1) % 2].n).first,
      P1(j + 1, tmp.second)));
}

signed main() {
  cin >> N;
  seg[0].init(N, 0);
  seg[1].init(N, 1);
  for (int i = 0; i < N; ++i) {
    int x;
    cin >> x;
    p.PB(x);
    seg[i % 2].update(i, P1(x, i));
  }
  minInterval.push(P2(seg[0].query(0, N, 0, 0, seg[0].n).first, P1(0, N)));
  for (int cnt = 0; cnt < N / 2; ++cnt) {
    P2 nextInterval = minInterval.top();
    int l = nextInterval.second.first, r = nextInterval.second.second;
    minInterval.pop();
    P1 i, j;
    i = seg[l % 2].query(l, r, 0, 0, seg[l % 2].n);
    j = seg[!(l % 2)].query(i.second + 1, r, 0, 0, seg[!(l % 2)].n);
    q.PB(i.first);
    q.PB(j.first);
    divideInterval(nextInterval.second, i.second, j.second);
  }
  for (int i = 0; i < q.size(); ++i)
    cout << q[i] << " ";
}


Fixed submission:
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define PB push_back
using namespace std;
typedef pair<int, int> P1;
typedef pair<int, pair<int, int>> P2;
static const int INF = 1ll << 60;
static const int dx[] = {
    1,
    -1,
    0,
    0,
};
static const int dy[] = {0, 0, 1, -1};
P1 dat[2][600005];

class Segment {
public:
  int n;
  int ed;
  void init(int n_, int ed_) {
    n = 1;
    ed = ed_;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; ++i)
      dat[ed][i] = P1(INF, INF);
  }

  P1 Min(P1 a, P1 b) {
    if (a.first <= b.first)
      return a;
    else
      return b;
  }

  void update(int k, P1 a) {
    k += n - 1;
    dat[ed][k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[ed][k] = Min(dat[ed][k * 2 + 1], dat[ed][k * 2 + 2]);
    }
  }

  P1 query(int a, int b, int k, int l, int r) {
    if (a <= l && r <= b)
      return dat[ed][k];
    if (r <= a || b <= l)
      return P1(INF, INF);
    else {
      P1 vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      P1 vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return Min(vl, vr);
    }
  }
};

int N;
vector<int> p, q;
vector<P1> interval;
priority_queue<P2, vector<P2>, greater<P2>> minInterval;
Segment seg[2];

void divideInterval(P1 id, int i, int j) {
  P1 tmp = id;
  minInterval.push(P2(
      seg[tmp.first % 2].query(tmp.first, i, 0, 0, seg[tmp.first % 2].n).first,
      P1(tmp.first, i)));
  minInterval.push(
      P2(seg[(i + 1) % 2].query(i + 1, j, 0, 0, seg[(i + 1) % 2].n).first,
         P1(i + 1, j)));
  minInterval.push(P2(
      seg[(j + 1) % 2].query(j + 1, tmp.second, 0, 0, seg[(j + 1) % 2].n).first,
      P1(j + 1, tmp.second)));
}

signed main() {
  cin >> N;
  seg[0].init(N, 0);
  seg[1].init(N, 1);
  for (int i = 0; i < N; ++i) {
    int x;
    cin >> x;
    p.PB(x);
    seg[i % 2].update(i, P1(x, i));
  }
  minInterval.push(P2(seg[0].query(0, N, 0, 0, seg[0].n).first, P1(0, N)));
  for (int cnt = 0; cnt < N / 2; ++cnt) {
    P2 nextInterval = minInterval.top();
    int l = nextInterval.second.first, r = nextInterval.second.second;
    minInterval.pop();
    P1 i, j;
    i = seg[l % 2].query(l, r, 0, 0, seg[l % 2].n);
    j = seg[!(l % 2)].query(i.second + 1, r, 0, 0, seg[!(l % 2)].n);
    q.PB(i.first);
    q.PB(j.first);
    divideInterval(nextInterval.second, i.second, j.second);
  }
  for (int i = 0; i < q.size(); ++i)
    cout << q[i] << " ";
}