Problem p00998 (C++) — buggy submission, verdict: Runtime Error

// #define NDEBUG

#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;
typedef long long ll;

template <class D> struct AASSTree {
  struct Node;
  typedef Node *NP;
  const static D INF = 1 << 30;
  static Node last_d;
  static NP last;
  struct Node {
    NP l, r;
    int level, sz;
    D v, mi, lz;
    bool rev;
    Node() : l(nullptr), r(nullptr), level(0), sz(0) {}
    Node(D vv) : l(last), r(last), level(1), sz(1) {
      v = vv;
      mi = vv;
      lz = 0;
      rev = false;
    }

    // メモリプールをしたい時のためにnewにはラッパを用意しておく
    static NP make() { return new Node(); }
    static NP make(D vv) { return new Node(vv); }
  } *n;

  static NP push(NP &n) {
    if (n == last)
      return n;
    if (n->lz) {
      if (n->l != last) {
        lzdata(n->l, n->lz);
      }
      if (n->r != last) {
        lzdata(n->r, n->lz);
      }
      n->lz = 0;
    }
    if (n->rev) {
      swap(n->l, n->r);
      revdata(n->l);
      revdata(n->r);
      n->rev = false;
      skew(n);
    }
    return n;
  }
  static NP revdata(NP n) {
    n->rev = !n->rev;
    return n;
  }
  // k番目の要素のポインタを取得する
  static NP at_ptr(NP &n, int k) {
    push(n);
    if (k == n->l->sz)
      return n;
    if (k < n->l->sz) {
      return at_ptr(n->l, k);
    } else {
      return at_ptr(n->r, k - (n->l->sz + 1));
    }
  }

  static void update(NP n) {
    assert(!n->lz);
    assert(!n->rev);
    n->sz = 1 + n->l->sz + n->r->sz;
    n->mi = n->v;
    if (n->l != last) {
      n->mi = min(n->mi, n->l->mi);
    }
    if (n->r != last) {
      n->mi = min(n->mi, n->r->mi);
    }
  }

  static void lzdata(NP n, D x) {
    n->v += x;
    n->mi += x;
    n->lz += x;
  }
  static D at(NP &n, int k) {
    push(n);
    if (k == n->l->sz)
      return n->v;
    if (k < n->l->sz) {
      return at(n->l, k);
    } else {
      return at(n->r, k - (n->l->sz + 1));
    }
  }
  static NP tp(NP &n, int dps = 0) {
    if (n == last)
      return n;
    dps = min(dps, 3);
    push(n);
    n->l = tp(n->l, dps + 1);
    cout << n->v << " ";
    n->r = tp(n->r, dps + 1);
    return n;
  }

  static void add(NP &n, int a, int b, D x) {
    if (n == last || b <= 0 || n->sz <= a)
      return;
    if (a <= 0 && n->sz <= b) {
      lzdata(n, x);
      return;
    }
    push(n);
    add(n->l, a, b, x);
    if (a <= n->l->sz && n->l->sz < b) {
      n->v += x;
    }
    add(n->r, a - (n->l->sz + 1), b - (n->l->sz + 1), x);
    update();
  }
  static D get(NP &n, int a, int b) {
    if (n == last || b <= 0 || n->sz <= a)
      return INF;
    if (a <= 0 && n->sz <= b) {
      return n->mi;
    }
    push(n);
    D res = INF;
    res = min(res, get(n->l, a, b));
    if (a <= n->l->sz && n->l->sz < b) {
      res = min(res, n->v);
    }
    res = min(res, get(n->r, a - (n->l->sz + 1), b - (n->l->sz + 1)));
    return res;
  }
  static NP set(NP &n, int k, D x) {
    assert(n != last);
    push(n);
    if (k == n->l->sz) {
      n->v = x;
      update(n);
      return n;
    }
    if (k < n->l->sz) {
      n->l = set(n->l, k, x);
    } else {
      n->r = set(n->r, k - (n->l->sz + 1), x);
    }
    update(n);
    return n;
  }
  static void allpush(NP &n) {
    if (n == last)
      return;
    push(n);
    allpush(n->l);
    allpush(n->r);
  }
  static NP built(int sz, D d[]) {
    if (!sz)
      return last;
    int md = (sz - 1) / 2;
    NP n = Node::make(d[md]);
    n->l = built(md, d);
    n->r = built(sz - (md + 1), d + (md + 1));
    n->level = n->l->level + 1;
    update(n);
    return n;
  }
  AASSTree() : n(last) {}
  AASSTree(NP n) : n(n) {}
  // 木の初期化はn回insertより一気に作る方が有意に速くなる事が多い
  AASSTree(int sz, D d[]) { n = built(sz, d); }

  // AA木の基本動作であるskew/split
  // splitは名前が紛らわしいためpullに変更してある
  static void skew(NP &n) {
    push(n);
    if (n->level == n->l->level) {
      NP L = push(n->l);
      n->l = L->r;
      L->r = n;
      update(n);
      update(L);
      n = L;
    }
  }
  static void pull(NP &n) {
    push(n);
    if (n->level == n->r->level && n->r->level == n->r->r->level) {
      NP R = push(n->r);
      n->r = R->l;
      R->l = n;
      R->level++;
      update(n);
      update(R);
      n = R;
    }
  }

  static NP insert(NP &n, int k, D x) {
    if (n == last) {
      assert(k == 0);
      return Node::make(x);
    }
    push(n);
    if (k <= n->l->sz) {
      n->l = insert(n->l, k, x);
      update(n);
    } else {
      n->r = insert(n->r, k - (n->l->sz + 1), x);
      update(n);
    }
    n = skew(n);
    n = pull(n);
    return n;
  }
  static NP leftdown(NP &n) {
    assert(n->l->level < n->level);
    if (n->l->level == n->level - 1)
      return n;
    n->level--;
    if (n->r->level == n->level) {
      pull(n);
    } else {
      n->r->level--;
      skew(n->r);
      skew(n->r->r);
      pull(n);
      pull(n->r);
    }
    return n;
  }
  static NP rightdown(NP n) {
    assert(n->r->level <= n->level);
    if (n->r->level >= n->level - 1)
      return n;
    n->level--;
    skew(n);
    skew(n->r);
    pull(n);
    return n;
  }
  static NP superleftdown(NP n) {
    if (n->l->level == n->level - 1)
      return n;
    if (n->level != n->r->level && n->r->level != n->r->r->level) {
      n->level--;
      return superleftdown(n);
    }
    n = leftdown(n);
    n->l = superleftdown(n->l);
    n = leftdown(n);
    return n;
  }
  static NP superrightdown(NP n) {
    if (n->r->level >= n->level - 1)
      return n;
    n = rightdown(n);
    n->r = superrightdown(n->r);
    n = rightdown(n);
    return n;
  }

  // pair<0番目の要素,0番目の要素を削除した木>
  static pair<NP, NP> at0_with_remove(NP &n) {
    assert(n != last);
    push(n);
    if (n->l == last) {
      return {n, n->r};
    }
    auto x = at0_with_remove(n->l);
    n->l = x.second;
    update(n);
    x.second = leftdown(n);
    return x;
  }
  static NP remove(NP &n, int k) {
    assert(n != last);
    push(n);
    if (k == n->l->sz) {
      if (n->level == 1) {
        return n->r;
      }
      auto x = at0_with_remove(n->r);
      NP nn = push(x.first);
      nn->l = n->l;
      nn->r = x.second;
      nn->level = n->level;
      update(nn);
      return rightdown(nn);
    }
    if (k < n->l->sz) {
      n->l = remove(n->l, k);
      update(n);
      return leftdown(n);
    } else {
      n->r = remove(n->r, k - (n->l->sz + 1));
      update(n);
      return rightdown(n);
    }
  }
  static NP merge(NP l, NP r) {
    if (l == last)
      return r;
    if (r == last)
      return l;
    if (l->level == r->level) {
      auto x = at0_with_remove(r);
      NP n = push(x.first);
      n->r = x.second;
      n->l = l;
      n->level = l->level + 1;
      update(n);
      return rightdown(n);
    }
    NP n;
    if (l->level > r->level) {
      push(l);
      l->r = merge(l->r, r);
      update(l);
      n = l;
    } else {
      push(r);
      r->l = merge(l, r->l);
      update(r);
      n = r;
    }
    skew(n);
    pull(n);
    return n;
  }
  static pair<NP, NP> split(NP &n, int k) {
    if (n == last)
      return {last, last};
    // printf("split %d %d %d %d\\n", k, n->sz, n->l->v, n->l->sz);
    push(n);
    if (k <= n->l->sz) {
      auto y = split(n->l, k);
      n->l = y.second;
      update(n);
      n = superleftdown(n);
      y.second = n;
      return y;
    } else {
      auto y = split(n->r, k - (n->l->sz + 1));
      n->r = y.first;
      update(n);
      n = superrightdown(n);
      y.first = n;
      return y;
    }
  }

  int sz() {
    push(n);
    return n->sz;
  }
  // 基本動作
  void merge(AASSTree r) { n = merge(n, r.n); }
  AASSTree split(int k) {
    auto y = split(n, k);
    n = y.first;
    return AASSTree(y.second);
  }
  void insert(int k, D x) { n = insert(n, k, x); }
  void remove(int k) { n = remove(n, k); }
  D at(int k) { return at(n, k); }
  void rev(int l, int r) {
    auto t2 = split(r);
    auto t1 = split(l);
    revdata(t1.n);
    merge(t1);
    merge(t2);
  }
  void tp() {
    push(n);
    tp(n);
    printf("\\n");
  }
  void add(int l, int r, D x) {
    push(n);
    add(n, l, r, x);
  }
  void set(int k, D x) {
    push(n);
    set(n, k, x);
  }
  D get(int l, int r) {
    push(n);
    return get(n, l, r);
  }
  void allpush() {
    n = allpush(n);
    return;
  }
};
template <class D>
typename AASSTree<D>::Node AASSTree<D>::last_d = AASSTree<D>::Node();
template <class D>
typename AASSTree<D>::NP AASSTree<D>::last = &AASSTree<D>::last_d;

const int MN = 200200;
int a[MN];
int main() {
  int n, q;
  scanf("%d %d", &n, &q);
  for (int i = 0; i < n; i++) {
    scanf("%d", a + i);
  }
  AASSTree<int> atr(n, a);
  for (int i = 0; i < q; i++) {
    //        printf("size %d\\n", atr.sz());
    int x, y, z;
    scanf("%d %d %d", &x, &y, &z);
    if (x == 0) {
      int l = y, r = z;
      //            int tmp = atr.at(r);
      //            atr.remove(r);
      //            atr.insert(l, tmp);
      atr.rev(l, r + 1);
      atr.rev(l + 1, r + 1);
      //            printf("revends %d\\n", atr.sz());
    } else if (x == 1) {
      int l = y, r = z;
      r++;
      printf("%d\\n", atr.get(l, r));
      //            printf("getends %d\\n", atr.sz());
    } else {
      int l = y, val = z;
      atr.set(l, val);
      //            printf("setends %d\\n", atr.sz());
    }
    //        atr.tp();
  }
  return 0;
}

Error: 0

Fixed submission:

#define NDEBUG

#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;
typedef long long ll;

template <class D> struct AASSTree {
  struct Node;
  typedef Node *NP;
  const static D INF = 1 << 30;
  static Node last_d;
  static NP last;
  struct Node {
    NP l, r;
    int level, sz;
    D v, mi, lz;
    bool rev;
    Node() : l(nullptr), r(nullptr), level(0), sz(0) {}
    Node(D vv) : l(last), r(last), level(1), sz(1) {
      v = vv;
      mi = vv;
      lz = 0;
      rev = false;
    }

    // メモリプールをしたい時のためにnewにはラッパを用意しておく
    static NP make() { return new Node(); }
    static NP make(D vv) { return new Node(vv); }
  } *n;

  static NP push(NP n) {
    if (n == last)
      return n;
    if (n->lz) {
      if (n->l != last) {
        lzdata(n->l, n->lz);
      }
      if (n->r != last) {
        lzdata(n->r, n->lz);
      }
      n->lz = 0;
    }
    if (n->rev) {
      swap(n->l, n->r);
      revdata(n->l);
      revdata(n->r);
      n->rev = false;
      n = skew(n);
    }
    return n;
  }
  static NP revdata(NP n) {
    n->rev = !n->rev;
    return n;
  }
  // k番目の要素のポインタを取得する
  static NP at_ptr(NP n, int k) {
    n = push(n);
    if (k == n->l->sz)
      return n;
    if (k < n->l->sz) {
      return at_ptr(n->l, k);
    } else {
      return at_ptr(n->r, k - (n->l->sz + 1));
    }
  }

  static void update(NP n) {
    assert(!n->lz);
    assert(!n->rev);
    n->sz = 1 + n->l->sz + n->r->sz;
    n->mi = n->v;
    if (n->l != last) {
      n->mi = min(n->mi, n->l->mi);
    }
    if (n->r != last) {
      n->mi = min(n->mi, n->r->mi);
    }
  }

  static void lzdata(NP n, D x) {
    n->v += x;
    n->mi += x;
    n->lz += x;
  }
  static D at(NP n, int k) {
    n = push(n);
    if (k == n->l->sz)
      return n->v;
    if (k < n->l->sz) {
      return at(n->l, k);
    } else {
      return at(n->r, k - (n->l->sz + 1));
    }
  }
  static NP tp(NP n, int dps = 0) {
    if (n == last)
      return n;
    dps = min(dps, 3);
    n = push(n);
    n->l = tp(n->l, dps + 1);
    cout << n->v << " ";
    n->r = tp(n->r, dps + 1);
    return n;
  }

  static void add(NP n, int a, int b, D x) {
    if (n == last || b <= 0 || n->sz <= a)
      return;
    if (a <= 0 && n->sz <= b) {
      lzdata(n, x);
      return;
    }
    n = push(n);
    add(n->l, a, b, x);
    if (a <= n->l->sz && n->l->sz < b) {
      n->v += x;
    }
    add(n->r, a - (n->l->sz + 1), b - (n->l->sz + 1), x);
    update();
  }
  static D get(NP n, int a, int b) {
    if (n == last || b <= 0 || n->sz <= a)
      return INF;
    if (a <= 0 && n->sz <= b) {
      return n->mi;
    }
    n = push(n);
    D res = INF;
    res = min(res, get(n->l, a, b));
    if (a <= n->l->sz && n->l->sz < b) {
      res = min(res, n->v);
    }
    res = min(res, get(n->r, a - (n->l->sz + 1), b - (n->l->sz + 1)));
    return res;
  }
  static void set(NP n, int k, D x) {
    n = push(n);
    if (k == n->l->sz) {
      n->v = x;
      update(n);
      return;
    }
    if (k < n->l->sz) {
      set(n->l, k, x);
    } else {
      set(n->r, k - (n->l->sz + 1), x);
    }
    update(n);
    return;
  }
  static void allpush(NP n) {
    if (n == last)
      return;
    n = push(n);
    allpush(n->l);
    allpush(n->r);
  }
  static NP built(int sz, D d[]) {
    if (!sz)
      return last;
    int md = (sz - 1) / 2;
    NP n = Node::make(d[md]);
    n->l = built(md, d);
    n->r = built(sz - (md + 1), d + (md + 1));
    n->level = n->l->level + 1;
    update(n);
    return n;
  }
  AASSTree() : n(last) {}
  AASSTree(NP n) : n(n) {}
  // 木の初期化はn回insertより一気に作る方が有意に速くなる事が多い
  AASSTree(int sz, D d[]) { n = built(sz, d); }

  // AA木の基本動作であるskew/split
  // splitは名前が紛らわしいためpullに変更してある
  static NP skew(NP n) {
    n = push(n);
    if (n->level == n->l->level) {
      NP L = push(n->l);
      n->l = L->r;
      L->r = n;
      update(n);
      update(L);
      return L;
    }
    return n;
  }
  static NP pull(NP n) {
    n = push(n);
    if (n->level == n->r->level && n->r->level == n->r->r->level) {
      NP R = push(n->r);
      n->r = R->l;
      R->l = n;
      R->level++;
      update(n);
      update(R);
      return R;
    }
    return n;
  }

  static NP insert(NP n, int k, D x) {
    if (n == last) {
      assert(k == 0);
      return Node::make(x);
    }
    n = push(n);
    if (k <= n->l->sz) {
      n->l = insert(n->l, k, x);
      update(n);
    } else {
      n->r = insert(n->r, k - (n->l->sz + 1), x);
      update(n);
    }
    n = skew(n);
    n = pull(n);
    return n;
  }
  static NP leftdown(NP n) {
    assert(n->l->level < n->level);
    if (n->l->level == n->level - 1)
      return n;
    n->level--;
    if (n->r->level == n->level) {
      n = pull(n);
    } else {
      n->r->level--;
      n->r = skew(n->r);
      n->r->r = skew(n->r->r);
      n = pull(n);
      n->r = pull(n->r);
    }
    return n;
  }
  static NP rightdown(NP n) {
    assert(n->r->level <= n->level);
    if (n->r->level >= n->level - 1)
      return n;
    n->level--;
    n = skew(n);
    n->r = skew(n->r);
    n = pull(n);
    return n;
  }
  static NP superleftdown(NP n) {
    if (n->l->level == n->level - 1)
      return n;
    if (n->level != n->r->level && n->r->level != n->r->r->level) {
      n->level--;
      return superleftdown(n);
    }
    n = leftdown(n);
    n->l = superleftdown(n->l);
    n = leftdown(n);
    return n;
  }
  static NP superrightdown(NP n) {
    if (n->r->level >= n->level - 1)
      return n;
    n = rightdown(n);
    n->r = superrightdown(n->r);
    n = rightdown(n);
    return n;
  }

  // pair<0番目の要素,0番目の要素を削除した木>
  static pair<NP, NP> at0_with_remove(NP n) {
    assert(n != last);
    n = push(n);
    if (n->l == last) {
      return {n, n->r};
    }
    auto x = at0_with_remove(n->l);
    n->l = x.second;
    update(n);
    x.second = leftdown(n);
    return x;
  }
  static NP remove(NP n, int k) {
    assert(n != last);
    n = push(n);
    if (k == n->l->sz) {
      if (n->level == 1) {
        return n->r;
      }
      auto x = at0_with_remove(n->r);
      NP nn = push(x.first);
      nn->l = n->l;
      nn->r = x.second;
      nn->level = n->level;
      update(nn);
      return rightdown(nn);
    }
    if (k < n->l->sz) {
      n->l = remove(n->l, k);
      update(n);
      return leftdown(n);
    } else {
      n->r = remove(n->r, k - (n->l->sz + 1));
      update(n);
      return rightdown(n);
    }
  }
  static NP merge(NP l, NP r) {
    if (l == last)
      return r;
    if (r == last)
      return l;
    if (l->level == r->level) {
      auto x = at0_with_remove(r);
      NP n = push(x.first);
      n->r = x.second;
      n->l = l;
      n->level = l->level + 1;
      update(n);
      return rightdown(n);
    }
    NP n;
    if (l->level > r->level) {
      l = push(l);
      l->r = merge(l->r, r);
      update(l);
      n = l;
    } else {
      r = push(r);
      r->l = merge(l, r->l);
      update(r);
      n = r;
    }
    n = skew(n);
    n = pull(n);
    return n;
  }
  static pair<NP, NP> split(NP n, int k) {
    if (n == last)
      return {last, last};
    // printf("split %d %d %d %d\\n", k, n->sz, n->l->v, n->l->sz);
    n = push(n);
    if (k <= n->l->sz) {
      auto y = split(n->l, k);
      n->l = y.second;
      update(n);
      n = superleftdown(n);
      y.second = n;
      return y;
    } else {
      auto y = split(n->r, k - (n->l->sz + 1));
      n->r = y.first;
      update(n);
      n = superrightdown(n);
      y.first = n;
      return y;
    }
  }

  int sz() { return n->sz; }
  // 基本動作
  void merge(AASSTree r) { n = merge(n, r.n); }
  AASSTree split(int k) {
    auto y = split(n, k);
    n = y.first;
    return AASSTree(y.second);
  }
  void insert(int k, D x) { n = insert(n, k, x); }
  void remove(int k) { n = remove(n, k); }
  D at(int k) { return at(n, k); }
  void rev(int l, int r) {
    auto t2 = split(r);
    auto t1 = split(l);
    revdata(t1.n);
    merge(t1);
    merge(t2);
  }
  void tp() {
    n = push(n);
    tp(n);
    printf("\\n");
  }
  void add(int l, int r, D x) {
    n = push(n);
    add(n, l, r, x);
  }
  void set(int k, D x) {
    n = push(n);
    set(n, k, x);
  }
  D get(int l, int r) {
    n = push(n);
    return get(n, l, r);
  }
  void allpush() {
    n = allpush(n);
    return;
  }
};
template <class D>
typename AASSTree<D>::Node AASSTree<D>::last_d = AASSTree<D>::Node();
template <class D>
typename AASSTree<D>::NP AASSTree<D>::last = &AASSTree<D>::last_d;

const int MN = 200200;
int a[MN];
int main() {
  int n, q;
  scanf("%d %d", &n, &q);
  for (int i = 0; i < n; i++) {
    scanf("%d", a + i);
  }
  AASSTree<int> atr(n, a);
  for (int i = 0; i < q; i++) {
    int x, y, z;
    scanf("%d %d %d", &x, &y, &z);
    if (x == 0) {
      int l = y, r = z;
      //            int tmp = atr.at(r);
      //            atr.remove(r);
      //            atr.insert(l, tmp);
      atr.rev(l, r + 1);
      atr.rev(l + 1, r + 1);
    } else if (x == 1) {
      int l = y, r = z;
      r++;
      printf("%d\\n", atr.get(l, r));
    } else {
      int l = y, val = z;
      atr.set(l, val);
    }
    // atr.tp();
  }
  return 0;
}