Problem p03641 (C++)

Buggy submission (status: Runtime Error):
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <functional>
#include <map>
#include <set>
#include <vector>

#include <iostream>
#include <sstream>

using namespace std;
typedef long long llint;
const llint inf = 1000000000000000000LL;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

#define TRACE(x) cerr << #x << " = " << x << endl
#define _ << " _ " <<

struct Tournament {
  static const int off = 1 << 18;

  struct Node {
    int minval[2];
    int minidx[2];
    int side;
    int prop;

    Node() {
      memset(minval, 0x3f, sizeof minval);
      memset(minidx, -1, sizeof minidx);
      side = prop = 0;
    }

    int &min_val(int i) { return minval[i ^ side]; }

    int &min_idx(int i) { return minidx[i ^ side]; }

    void flip(int p) {
      side ^= p;
      prop ^= p;
    }
  };

  Node merge(Node &a, Node &b) {
    Node result;

    REP(r, 2) {
      Node *best = nullptr;
      if (a.min_val(r) < b.min_val(r))
        best = &a;
      else
        best = &b;
      result.min_val(r) = best->min_val(r);
      result.min_idx(r) = best->min_idx(r);
    }

    return result;
  }

  Node tree[off << 1];

  void init(const vector<int> &v, int i = 1) {
    tree[i] = Node();

    if (i >= off) {
      int idx = i - off;
      if (idx < (int)v.size()) {
        tree[i].min_val(idx % 2) = v[idx];
        tree[i].min_idx(idx % 2) = idx;
      }
      return;
    }

    init(v, 2 * i);
    init(v, 2 * i + 1);
    tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
  }

  void propagate(int i) {
    Node &l = tree[2 * i];
    Node &r = tree[2 * i + 1];
    l.flip(tree[i].prop);
    r.flip(tree[i].prop);
    tree[i].prop = 0;
  }

  void flip(int l, int r, int lo = 0, int hi = off, int i = 1) {
    if (lo >= r || hi <= l)
      return;
    if (lo >= l && hi <= r) {
      tree[i].flip(1);
      return;
    }

    propagate(i);

    int mid = (lo + hi) / 2;
    flip(l, r, lo, mid, 2 * i);
    flip(l, r, mid, hi, 2 * i + 1);
    tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
  }

  void prop_path(int i) {
    if (i > 1)
      prop_path(i / 2);
    propagate(i);
  }

  void pop(int idx) {
    idx += off;
    prop_path(idx);
    tree[idx] = Node();
    for (idx /= 2; idx; idx /= 2)
      tree[idx] = merge(tree[2 * idx], tree[2 * idx + 1]);
  }

  Node query(int l, int r, int lo = 0, int hi = off, int i = 1) {
    if (lo >= r || hi <= l)
      return Node();
    if (lo >= l && hi <= r)
      return tree[i];

    propagate(i);

    int mid = (lo + hi) / 2;
    auto L = query(l, r, lo, mid, 2 * i);
    auto R = query(l, r, mid, hi, 2 * i + 1);
    return merge(L, R);
  }
} t;

int main(void) {
  int N;
  scanf("%d", &N);

  vector<int> p(N);
  REP(i, N) scanf("%d", &p[i]);

  t.init(p);
  set<int> dead;
  dead.insert(N);

  vector<int> sol;

  REP(i, N / 2) {
    int idxa = t.query(0, N).min_idx(0);
    sol.push_back(p[idxa]);

    int to = *dead.lower_bound(idxa);
    int idxb = t.query(idxa, to).min_idx(1);
    sol.push_back(p[idxb]);

    t.flip(idxa + 1, idxb);

    t.pop(idxa);
    t.pop(idxb);

    dead.insert(idxa);
    dead.insert(idxb);
  }

  REP(i, N)
  printf("%d%c", sol[i], " \n"[i + 1 == N]);

  return 0;
}


Fixed submission:
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <functional>
#include <map>
#include <set>
#include <vector>

#include <iostream>
#include <sstream>

using namespace std;
typedef long long llint;
const llint inf = 1000000000000000000LL;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

#define TRACE(x) cerr << #x << " = " << x << endl
#define _ << " _ " <<

struct Tournament {
  static const int off = 1 << 18;

  struct Node {
    int minval[2];
    int minidx[2];
    int side;
    int prop;

    Node() {
      memset(minval, 0x3f, sizeof minval);
      memset(minidx, -1, sizeof minidx);
      side = prop = 0;
    }

    int &min_val(int i) { return minval[i ^ side]; }

    int &min_idx(int i) { return minidx[i ^ side]; }

    void flip(int p) {
      side ^= p;
      prop ^= p;
    }
  };

  Node merge(Node &a, Node &b) {
    Node result;

    REP(r, 2) {
      Node *best = nullptr;
      if (a.min_val(r) < b.min_val(r))
        best = &a;
      else
        best = &b;
      result.min_val(r) = best->min_val(r);
      result.min_idx(r) = best->min_idx(r);
    }

    return result;
  }

  Node tree[off << 1];

  void init(const vector<int> &v, int i = 1) {
    tree[i] = Node();

    if (i >= off) {
      int idx = i - off;
      if (idx < (int)v.size()) {
        tree[i].min_val(idx % 2) = v[idx];
        tree[i].min_idx(idx % 2) = idx;
      }
      return;
    }

    init(v, 2 * i);
    init(v, 2 * i + 1);
    tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
  }

  void propagate(int i) {
    Node &l = tree[2 * i];
    Node &r = tree[2 * i + 1];
    l.flip(tree[i].prop);
    r.flip(tree[i].prop);
    tree[i].prop = 0;
  }

  void flip(int l, int r, int lo = 0, int hi = off, int i = 1) {
    if (lo >= r || hi <= l)
      return;
    if (lo >= l && hi <= r) {
      tree[i].flip(1);
      return;
    }

    propagate(i);

    int mid = (lo + hi) / 2;
    flip(l, r, lo, mid, 2 * i);
    flip(l, r, mid, hi, 2 * i + 1);
    tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
  }

  void prop_path(int i) {
    if (i > 1)
      prop_path(i / 2);
    propagate(i);
  }

  void pop(int idx) {
    idx += off;
    prop_path(idx / 2);
    tree[idx] = Node();
    for (idx /= 2; idx; idx /= 2)
      tree[idx] = merge(tree[2 * idx], tree[2 * idx + 1]);
  }

  Node query(int l, int r, int lo = 0, int hi = off, int i = 1) {
    if (lo >= r || hi <= l)
      return Node();
    if (lo >= l && hi <= r)
      return tree[i];

    propagate(i);

    int mid = (lo + hi) / 2;
    auto L = query(l, r, lo, mid, 2 * i);
    auto R = query(l, r, mid, hi, 2 * i + 1);
    return merge(L, R);
  }
} t;

int main(void) {
  int N;
  scanf("%d", &N);

  vector<int> p(N);
  REP(i, N) scanf("%d", &p[i]);

  t.init(p);
  set<int> dead;
  dead.insert(N);

  vector<int> sol;

  REP(i, N / 2) {
    int idxa = t.query(0, N).min_idx(0);
    sol.push_back(p[idxa]);

    int to = *dead.lower_bound(idxa);
    int idxb = t.query(idxa, to).min_idx(1);
    sol.push_back(p[idxb]);

    t.flip(idxa + 1, idxb);

    t.pop(idxa);
    t.pop(idxb);

    dead.insert(idxa);
    dead.insert(idxb);
  }

  REP(i, N)
  printf("%d%c", sol[i], " \n"[i + 1 == N]);

  return 0;
}