Problem p03673 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <iostream>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 100010;

// 变量
int n, m, root;
int a[maxn] = {0};
int ch[maxn][2];     // 记录儿子，0为左儿子，1为右儿子
int val[maxn];       // 当前点对应的值
int fa[maxn];        // 记录当前结点的父亲
int siz[maxn] = {0}; // 记录子树大小
int mx[maxn];        // 记录区间最值
int tag1[maxn];      // 区间加的标记
int tag2[maxn];      // 区间翻转的标记

inline void refresh(int now) { // 对于不同题而言，更新信息也不同
  if (!now)
    return;
  siz[now] = siz[ch[now][0]] + siz[ch[now][1]] + 1;
  mx[now] = max(val[now], max(mx[ch[now][0]], mx[ch[now][1]]));
}

int build(int l, int r, int f) {
  if (l > r)
    return 0;
  int mid = l + r >> 1;
  fa[mid] = f;
  val[mid] = a[mid];
  ch[mid][0] = build(l, mid - 1, mid);
  ch[mid][1] = build(mid + 1, r, mid);
  refresh(mid);
  return mid;
}

void pushdown(int now) { // 标记下传
  if (tag1[now]) {
    if (ch[now][0]) {
      tag1[ch[now][0]] += tag1[now];
      mx[ch[now][0]] += tag1[now];
      val[ch[now][0]] += tag1[now];
    }
    if (ch[now][1]) {
      tag1[ch[now][1]] += tag1[now];
      mx[ch[now][1]] += tag1[now];
      val[ch[now][1]] += tag1[now];
    }
    tag1[now] = 0;
  }
  if (tag2[now]) {
    if (ch[now][0]) {
      tag2[ch[now][0]] ^= 1;
      swap(ch[ch[now][0]][0], ch[ch[now][0]][1]);
    }
    if (ch[now][1]) {
      tag2[ch[now][1]] ^= 1;
      swap(ch[ch[now][1]][0], ch[ch[now][1]][1]);
    }
    tag2[now] = 0;
  }
}

int chk(
    int x) { // 判断这个结点是父亲的左儿子还是右儿子，是左儿子返回0，是右儿子返回1
  return ch[fa[x]][1] == x;
}

void rotate(int now) { // 旋转操作
  int f = fa[now], gf = fa[f], k = chk(now), w = ch[now][k ^ 1];
  ch[f][k] = w;
  fa[w] = f;
  ch[gf][chk(f)] = now;
  fa[now] = gf;
  ch[now][k ^ 1] = f;
  fa[f] = now;
  refresh(f);
  refresh(now);
}

void splay(int now, int goal = 0) { // 伸展操作
  while (fa[now] != goal) {
    int f = fa[now], gf = fa[f];
    if (gf != goal) {
      if (chk(f) == chk(now))
        rotate(f);
      else
        rotate(now);
    }
    rotate(now);
  }
  if (!goal)
    root = now;
}

int kth(int k) {  // 查询第k大结点
  int now = root; // 从根结点开始搜索
  while (1) {
    pushdown(now); // 多一个pushdown
    if (ch[now][0] && k <= siz[ch[now][0]]) {
      // 如果有左子树且左子树大小大于等于k，说明k在左子树上
      now = ch[now][0];
    } else if (k > siz[ch[now][0]] + 1) {
      // 否则如果左子树加上当前结点的大小依然小于k，说明在右子树上
      k -= siz[ch[now][0]] + 1;
      now = ch[now][1];
    } else { // 否则说明第k大就是当前结点
      return now;
    }
  }
}

int split(int l, int r) {
  l = kth(l);
  r = kth(r + 2);
  splay(l);
  splay(r, l);
  return ch[r][0];
}

void updata(int l, int r, int data) {
  int now = split(l, r);
  tag1[now] += data;
  mx[now] += data;
  val[now] += data;
}

void turn(int l, int r) {
  int now = split(l, r);
  tag2[now] ^= 1;
  swap(ch[now][0], ch[now][1]);
}

int query(int l, int r) { return mx[split(l, r)]; }

void dfs(int now) {
  pushdown(now);
  if (ch[now][0])
    dfs(ch[now][0]);
  if (val[now] != -INF)
    printf("%d ", val[now]);
  if (ch[now][1])
    dfs(ch[now][1]);
}

int main() {
  scanf("%d", &n);
  a[1] = -INF;
  a[n + 2] = -INF;
  mx[0] = -INF;
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i + 1]);
  }
  root = build(1, n + 2, 0);
  for (int i = 1; i <= n; ++i) {
    turn(1, i);
  }
  dfs(root);
  putchar('\n');
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <iostream>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 1000010;

// 变量
int n, m, root;
int a[maxn] = {0};
int ch[maxn][2];     // 记录儿子，0为左儿子，1为右儿子
int val[maxn];       // 当前点对应的值
int fa[maxn];        // 记录当前结点的父亲
int siz[maxn] = {0}; // 记录子树大小
int mx[maxn];        // 记录区间最值
int tag1[maxn];      // 区间加的标记
int tag2[maxn];      // 区间翻转的标记

inline void refresh(int now) { // 对于不同题而言，更新信息也不同
  if (!now)
    return;
  siz[now] = siz[ch[now][0]] + siz[ch[now][1]] + 1;
  mx[now] = max(val[now], max(mx[ch[now][0]], mx[ch[now][1]]));
}

int build(int l, int r, int f) {
  if (l > r)
    return 0;
  int mid = l + r >> 1;
  fa[mid] = f;
  val[mid] = a[mid];
  ch[mid][0] = build(l, mid - 1, mid);
  ch[mid][1] = build(mid + 1, r, mid);
  refresh(mid);
  return mid;
}

void pushdown(int now) { // 标记下传
  if (tag1[now]) {
    if (ch[now][0]) {
      tag1[ch[now][0]] += tag1[now];
      mx[ch[now][0]] += tag1[now];
      val[ch[now][0]] += tag1[now];
    }
    if (ch[now][1]) {
      tag1[ch[now][1]] += tag1[now];
      mx[ch[now][1]] += tag1[now];
      val[ch[now][1]] += tag1[now];
    }
    tag1[now] = 0;
  }
  if (tag2[now]) {
    if (ch[now][0]) {
      tag2[ch[now][0]] ^= 1;
      swap(ch[ch[now][0]][0], ch[ch[now][0]][1]);
    }
    if (ch[now][1]) {
      tag2[ch[now][1]] ^= 1;
      swap(ch[ch[now][1]][0], ch[ch[now][1]][1]);
    }
    tag2[now] = 0;
  }
}

int chk(
    int x) { // 判断这个结点是父亲的左儿子还是右儿子，是左儿子返回0，是右儿子返回1
  return ch[fa[x]][1] == x;
}

void rotate(int now) { // 旋转操作
  int f = fa[now], gf = fa[f], k = chk(now), w = ch[now][k ^ 1];
  ch[f][k] = w;
  fa[w] = f;
  ch[gf][chk(f)] = now;
  fa[now] = gf;
  ch[now][k ^ 1] = f;
  fa[f] = now;
  refresh(f);
  refresh(now);
}

void splay(int now, int goal = 0) { // 伸展操作
  while (fa[now] != goal) {
    int f = fa[now], gf = fa[f];
    if (gf != goal) {
      if (chk(f) == chk(now))
        rotate(f);
      else
        rotate(now);
    }
    rotate(now);
  }
  if (!goal)
    root = now;
}

int kth(int k) {  // 查询第k大结点
  int now = root; // 从根结点开始搜索
  while (1) {
    pushdown(now); // 多一个pushdown
    if (ch[now][0] && k <= siz[ch[now][0]]) {
      // 如果有左子树且左子树大小大于等于k，说明k在左子树上
      now = ch[now][0];
    } else if (k > siz[ch[now][0]] + 1) {
      // 否则如果左子树加上当前结点的大小依然小于k，说明在右子树上
      k -= siz[ch[now][0]] + 1;
      now = ch[now][1];
    } else { // 否则说明第k大就是当前结点
      return now;
    }
  }
}

int split(int l, int r) {
  l = kth(l);
  r = kth(r + 2);
  splay(l);
  splay(r, l);
  return ch[r][0];
}

void updata(int l, int r, int data) {
  int now = split(l, r);
  tag1[now] += data;
  mx[now] += data;
  val[now] += data;
}

void turn(int l, int r) {
  int now = split(l, r);
  tag2[now] ^= 1;
  swap(ch[now][0], ch[now][1]);
}

int query(int l, int r) { return mx[split(l, r)]; }

void dfs(int now) {
  pushdown(now);
  if (ch[now][0])
    dfs(ch[now][0]);
  if (val[now] != -INF)
    printf("%d ", val[now]);
  if (ch[now][1])
    dfs(ch[now][1]);
}

int main() {
  scanf("%d", &n);
  a[1] = -INF;
  a[n + 2] = -INF;
  mx[0] = -INF;
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i + 1]);
  }
  root = build(1, n + 2, 0);
  for (int i = 1; i <= n; ++i) {
    turn(1, i);
  }
  dfs(root);
  putchar('\n');
  return 0;
}