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

#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 AATree {
  struct Node;
  typedef Node *NP;
  constexpr static D INF = 1LL << 55;
  static Node last_d;
  static NP last;
  struct Node {
    NP l, r;
    int level, sz;
    D v, mi;
    Node() : l(nullptr), r(nullptr), level(0), sz(0) {}
    Node(D vv) : l(last), r(last), level(1), sz(1) {
      v = vv;
      mi = vv;
    }

    // メモリプール用 永続化を考えるとnewよりこちらを使う方が好ましい
    static NP make() { return new Node(); }
    static NP make(D vv) { return new Node(vv); }

    void update() {
      sz = 1 + l->sz + r->sz;
      mi = v;
      if (l->sz) {
        mi = min(mi, l->mi);
      }
      if (r->sz) {
        mi = min(mi, r->mi);
      }
    }

    NP get_ptr(int k) {
      if (k == l->sz)
        return this;
      if (k < l->sz) {
        return l->get_ptr(k);
      } else {
        return r->get_ptr(k - (l->sz + 1));
      }
    }
    D at(int k) {
      if (k == l->sz)
        return v;
      if (k < l->sz) {
        return l->at(k);
      } else {
        return r->at(k - (l->sz + 1));
      }
    }
    D minv(int a, int b) {
      if (!sz || b <= 0 || sz <= a)
        return INF;
      if (a <= 0 && sz <= b)
        return mi;
      D res = INF;
      res = min(res, l->minv(a, b));
      if (a <= l->sz && l->sz < b) {
        res = min(res, v);
      }
      res = min(res, r->minv(a - (l->sz + 1), b - (l->sz + 1)));
      return res;
    }
    void set(int k, D x) {
      if (k == l->sz) {
        v = x;
        update();
        return;
      }
      if (k < l->sz) {
        l->set(k, x);
      } else {
        r->set(k - (l->sz + 1), x);
      }
      update();
    }
    void tp(int dps = 0) {
      if (!sz)
        return;
      string s = "[{(", ss = "]})";
      dps = min(dps, 2);
      cout << s[dps];
      l->tp(dps + 1);
      cout << v << " ";
      r->tp(dps + 1);
      cout << ss[dps];
    }
    void allcheck() {
      if (sz) {
        assert(level);
      } else {
        assert(!level);
      }
      if (!sz)
        return;
      assert(l->level == level - 1);
      if (r->level == level) {
        assert(r->r->level == level - 1);
      }
      l->allcheck();
      r->allcheck();
    }
  } *n;
  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;
    n->update();
    return n;
  }
  AATree() : n(last) {}
  AATree(NP n) : n(n) {}
  AATree(int sz, D d[]) { n = built(sz, d); }

  NP skew(NP n) {
    if (n->level == n->l->level) {
      NP L = n->l;
      n->l = L->r;
      L->r = n;
      n->update();
      L->update();
      return L;
    }
    return n;
  }
  NP pull(NP n) {
    if (n->level == n->r->level && n->r->level == n->r->r->level) {
      NP R = n->r;
      n->r = R->l;
      R->l = n;
      R->level++;
      n->update();
      R->update();
      return R;
    }
    return n;
  }
  NP insert(NP n, int k, D x) {
    if (!n->sz) {
      assert(k == 0);
      return Node::make(x);
    }
    if (k <= n->l->sz) {
      n->l = insert(n->l, k, x);
      n->update();
      n = skew(n);
    } else {
      n->r = insert(n->r, k - (n->l->sz + 1), x);
      n->update();
    }
    n = pull(n);
    return n;
  }
  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;
  }
  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;
  }
  NP superleftdown(NP n) {
    if (n->l->level == n->level - 1)
      return n;
    bool f = n->level != n->r->level && n->r->level != n->r->r->level;
    n = leftdown(n);
    if (f) {
      n = superleftdown(n);
    } else {
      n->l = superleftdown(n->l);
    }
    n = superleftdown(n);
    return n;
  }
  NP superrightdown(NP n) {
    if (n->r->level >= n->level - 1)
      return n;
    n = rightdown(n);
    n->r = superrightdown(n->r);
    n = superrightdown(n);
    return n;
  }
  NP remove(NP n, int k) {
    if (k == n->l->sz) {
      if (n->level == 1) {
        // delete n
        return n->r;
      }
      Node nr = *(n->r->get_ptr(0));
      nr.l = n->l;
      nr.r = n->r;
      nr.level = n->level;
      nr.sz = n->sz;
      *n = nr;
      k = n->l->sz + 1;
    }
    if (k < n->l->sz) {
      n->l = remove(n->l, k);
      n->update();
      return leftdown(n);
    } else {
      n->r = remove(n->r, k - (n->l->sz + 1));
      n->update();
      return rightdown(n);
    }
  }
  NP merge(NP l, NP r) {
    if (!l->sz)
      return r;
    if (!r->sz)
      return l;
    NP n;
    if (l->level == r->level) {
      n = new Node();
      n->l = l;
      n->r = r;
      n->level = l->level + 1;
      n->sz = 1 + l->sz + r->sz;
      return remove(n, l->sz);
    }
    if (l->level > r->level) {
      l->r = merge(l->r, r);
      n = l;
    } else {
      r->l = merge(l, r->l);
      n = r;
    }
    n->update();
    n = skew(n);
    n = pull(n);
    return n;
  }
  void merge(AATree r) { n = merge(n, r.n); }
  pair<NP, NP> split(NP n, int k) {
    if (!n->sz)
      return {last, last};
    if (k <= n->l->sz) {
      auto y = split(n->l, k);
      n->l = y.second;
      n->update();
      n = superleftdown(n);
      y.second = n;
      return y;
    } else {
      auto y = split(n->r, k - (n->l->sz + 1));
      n->r = y.first;
      n->update();
      n = superrightdown(n);
      y.first = n;
      return y;
    }
  }
  AATree split(int k) {
    auto y = split(n, k);
    n = y.first;
    return AATree(y.second);
  }
  /*static pair<NP, NP> split(NP x, int k) {
      if (!x->sz) return {last, last};
      x->push();
      if (k <= x->l->sz) {
          auto y = split(x->l, k);
          x->l = y.second;
          y.second = x->update();
          return y;
      } else {
          auto y = split(x->r, k- x->l->sz -1);
          x->r = y.first;
          y.first = x->update();
          return y;
      }
  }*/
  void insert(D x) { n = insert(n, lb(x), x); }
  void insert_idx(int k, D x) { n = insert(n, k, x); }
  void erase(D x) { n = remove(n, lb(x)); }
  void remove(int k) { n = remove(n, k); }
  NP get_ptr(int k) {
    if (k < 0 || sz() <= k)
      return last;
    return n->get_ptr(k);
  }
  D at(int k) {
    assert(0 <= k && k < sz());
    return n->at(k);
  }
  int sz() { return n->sz; }
  D minv(int l, int r) { return n->minv(l, r); }
  void set(int k, D x) {
    n->set(k, x);
    return;
  }
  void tp() {
    n->tp();
    printf("\\n");
  }
  void allcheck() { n->allcheck(); }
};
template <class D>
typename AATree<D>::Node AATree<D>::last_d = AATree<D>::Node();
template <class D> typename AATree<D>::NP AATree<D>::last = &AATree<D>::last_d;

/*
const int N = 100;


ll a[110];
int main() {
    for (int i = 0; i < N; i++) {
        a[i] = rand() % 100;
    }
    AATree<ll> atr(N, a);
    for (int i = 0; i < 10000; i++) {
        int que = rand() % (N+1);
        printf("query %d\\n", que);
        auto nat = atr.split(que);
        nat.tp();
        atr.tp();
        nat.merge(atr);
        atr = nat;
        atr.tp();
        atr.allcheck();
    }
    return 0;
}*/

const int MN = 200200;
ll a[MN];
int main() {
  int n, q;
  cin >> n >> q;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  AATree<ll> atr(n, a);
  for (int i = 0; i < q; i++) {
    int x, y, z;
    cin >> x >> y >> z;
    if (x == 0) {
      int l = y, r = z;
      auto at0 = atr.split(r + 1);
      auto at1 = atr.split(r);
      auto at2 = atr.split(l);
      atr.merge(at1);
      atr.merge(at2);
      atr.merge(at0);
    } else if (x == 1) {
      int l = y, r = z;
      r++;
      printf("%lld\\n", atr.minv(l, r));
    } else {
      int l = y, val = z;
      atr.set(l, val);
    }
    // atr.tp();
  }
  return 0;
}

Error: 0

Fixed submission:

#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;
typedef pair<int, int> P;
struct STree {
  typedef ll D;
  const static D INF = 1LL << 55;
  struct Node;
  typedef Node *NP;
  static Node last_d;
  static NP last;
  struct Node {
    NP l, r;
    int sz;
    D v, mi;
    Node(D v) : l(last), r(last), sz(1), v(v), mi(v) {}
    Node(NP l, NP r, int sz = 0) : l(l), r(r), sz(sz) {}
    void push() {}
    NP update() {
      sz = 1 + l->sz + r->sz;
      mi = v;
      if (l->sz) {
        mi = min(mi, l->mi);
      }
      if (r->sz) {
        mi = min(mi, r->mi);
      }
      return this;
    }
    void print() {
      if (!sz)
        return;
      l->print();
      printf("%lld ", v);
      r->print();
    }
  } *n;

  static NP built(int l, int r, D d[]) {
    if (l == r)
      return last;
    int md = (l + r) / 2;
    NP x = new Node(d[md]);
    x->l = built(l, md, d);
    x->r = built(md + 1, r, d);
    return x->update();
  }

  static uint xor128() {
    static uint x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    uint t;
    t = (x ^ (x << 11));
    x = y;
    y = z;
    z = w;
    return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
  }
  static NP merge(NP l, NP r) {
    if (!l->sz)
      return r;
    if (!r->sz)
      return l;
    l->push();
    r->push();
    if (xor128() % (l->sz + r->sz) < l->sz) {
      l->r = merge(l->r, r);
      return l->update();
    } else {
      r->l = merge(l, r->l);
      return r->update();
    }
  }
  static pair<NP, NP> split(NP x, int k) {
    if (!x->sz)
      return {last, last};
    x->push();
    if (k <= x->l->sz) {
      auto y = split(x->l, k);
      x->l = y.second;
      y.second = x->update();
      return y;
    } else {
      auto y = split(x->r, k - x->l->sz - 1);
      x->r = y.first;
      y.first = x->update();
      return y;
    }
  }

  STree(NP n) : n(n) {}
  STree(int sz, D d[]) { n = built(0, sz, d); }
  int sz() { return n->sz; }
  void merge(STree r) { n = merge(n, r.n); }
  STree split(int k) {
    auto u = split(n, k);
    n = u.first;
    return STree(u.second);
  }
  void insert(int k, D x) {
    auto u = split(n, k);
    n = merge(merge(u.first, new Node(x)), u.second);
  }
  void erase(int k) {
    auto u = split(n, k);
    n = merge(u.first, split(u.second, 1).second);
  }
  ll get(int l, int r) {
    auto u0 = split(n, l);
    auto u1 = split(u0.second, r - l);
    ll res = u1.first->mi;
    n = merge(u0.first, merge(u1.first, u1.second));
    return res;
  }
  void set(int l, D x) {
    auto u0 = split(n, l);
    auto u1 = split(u0.second, 1);
    u1.first->v = x;
    u1.first->mi = x;
    n = merge(u0.first, merge(u1.first, u1.second));
  }
  void print() {
    n->print();
    printf("\\n");
  }
};
STree::Node STree::last_d = STree::Node(NULL, NULL, 0);
STree::NP STree::last = &last_d;
const int MN = 200200;

template <class D> struct AATree {
  struct Node;
  typedef Node *NP;
  constexpr static D INF = 1LL << 55;
  static Node last_d;
  static NP last;
  struct Node {
    NP l, r;
    int level, sz;
    D v, mi;
    Node() : l(nullptr), r(nullptr), level(0), sz(0) {}
    Node(D vv) : l(last), r(last), level(1), sz(1) {
      v = vv;
      mi = vv;
    }

    // メモリプール用 永続化を考えるとnewよりこちらを使う方が好ましい
    static NP make() { return new Node(); }
    static NP make(D vv) { return new Node(vv); }

    void update() {
      sz = 1 + l->sz + r->sz;
      mi = v;
      if (l->sz) {
        mi = min(mi, l->mi);
      }
      if (r->sz) {
        mi = min(mi, r->mi);
      }
    }

    NP get_ptr(int k) {
      if (k == l->sz)
        return this;
      if (k < l->sz) {
        return l->get_ptr(k);
      } else {
        return r->get_ptr(k - (l->sz + 1));
      }
    }
    D at(int k) {
      if (k == l->sz)
        return v;
      if (k < l->sz) {
        return l->at(k);
      } else {
        return r->at(k - (l->sz + 1));
      }
    }
    D minv(int a, int b) {
      if (!sz || b <= 0 || sz <= a)
        return INF;
      if (a <= 0 && sz <= b)
        return mi;
      D res = INF;
      res = min(res, l->minv(a, b));
      if (a <= l->sz && l->sz < b) {
        res = min(res, v);
      }
      res = min(res, r->minv(a - (l->sz + 1), b - (l->sz + 1)));
      return res;
    }
    void set(int k, D x) {
      if (k == l->sz) {
        v = x;
        update();
        return;
      }
      if (k < l->sz) {
        l->set(k, x);
      } else {
        r->set(k - (l->sz + 1), x);
      }
      update();
    }
    void tp() {
      if (!sz)
        return;
      l->tp();
      cout << v << " ";
      r->tp();
    }
  } *n;
  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;
    n->update();
    return n;
  }
  AATree() : n(last) {}
  AATree(NP n) : n(n) {}
  AATree(int sz, D d[]) { n = built(sz, d); }

  NP skew(NP n) {
    if (n->level == n->l->level) {
      NP L = n->l;
      n->l = L->r;
      L->r = n;
      n->update();
      L->update();
      return L;
    }
    return n;
  }
  NP pull(NP n) {
    if (n->level == n->r->level && n->r->level == n->r->r->level) {
      NP R = n->r;
      n->r = R->l;
      R->l = n;
      R->level++;
      n->update();
      R->update();
      return R;
    }
    return n;
  }
  NP insert(NP n, int k, D x) {
    if (!n->sz) {
      assert(k == 0);
      return Node::make(x);
    }
    if (k <= n->l->sz) {
      n->l = insert(n->l, k, x);
      n->update();
      n = skew(n);
    } else {
      n->r = insert(n->r, k - (n->l->sz + 1), x);
      n->update();
    }
    n = pull(n);
    return n;
  }
  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;
  }
  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;
  }
  NP superleftdown(NP n) {
    if (n->l->level == n->level - 1)
      return n;
    n = leftdown(n);
    n = superleftdown(n);
    n->l = superleftdown(n->l);
    n = superleftdown(n);
    return n;
  }
  NP superrightdown(NP n) {
    if (n->r->level >= n->level - 1)
      return n;
    n = rightdown(n);
    n->r = superrightdown(n->r);
    n = superrightdown(n);
    return n;
  }
  NP remove(NP n, int k) {
    if (k == n->l->sz) {
      if (n->level == 1) {
        // delete n
        return n->r;
      }
      Node nr = *(n->r->get_ptr(0));
      nr.l = n->l;
      nr.r = n->r;
      nr.level = n->level;
      nr.sz = n->sz;
      *n = nr;
      k = n->l->sz + 1;
    }
    if (k < n->l->sz) {
      n->l = remove(n->l, k);
      n->update();
      return leftdown(n);
    } else {
      n->r = remove(n->r, k - (n->l->sz + 1));
      n->update();
      return rightdown(n);
    }
  }
  NP merge(NP l, NP r) {
    if (!l->sz)
      return r;
    if (!r->sz)
      return l;
    NP n;
    if (l->level == r->level) {
      n = new Node();
      n->l = l;
      n->r = r;
      n->level = l->level + 1;
      n->sz = 1 + l->sz + r->sz;
      return remove(n, l->sz);
    }
    if (l->level > r->level) {
      l->r = merge(l->r, r);
      n = l;
    } else {
      r->l = merge(l, r->l);
      n = r;
    }
    n->update();
    n = skew(n);
    n = pull(n);
    return n;
  }
  void merge(AATree r) { n = merge(n, r.n); }
  pair<NP, NP> split(NP n, int k) {
    if (!n->sz)
      return {last, last};
    if (k <= n->l->sz) {
      auto y = split(n->l, k);
      n->l = y.second;
      n->update();
      n = superleftdown(n);
      //            while (n->l->level < n->level-1) n = leftdown(n);
      y.second = n;
      return y;
    } else {
      auto y = split(n->r, k - (n->l->sz + 1));
      n->r = y.first;
      n->update();
      n = superrightdown(n);
      //            while (n->r->level < n->level-1) n = rightdown(n);
      y.first = n;
      return y;
    }
  }
  AATree split(int k) {
    auto y = split(n, k);
    n = y.first;
    return AATree(y.second);
  }
  /*static pair<NP, NP> split(NP x, int k) {
      if (!x->sz) return {last, last};
      x->push();
      if (k <= x->l->sz) {
          auto y = split(x->l, k);
          x->l = y.second;
          y.second = x->update();
          return y;
      } else {
          auto y = split(x->r, k- x->l->sz -1);
          x->r = y.first;
          y.first = x->update();
          return y;
      }
  }*/
  void insert(D x) { n = insert(n, lb(x), x); }
  void insert_idx(int k, D x) { n = insert(n, k, x); }
  void erase(D x) { n = remove(n, lb(x)); }
  void remove(int k) { n = remove(n, k); }
  NP get_ptr(int k) {
    if (k < 0 || sz() <= k)
      return last;
    return n->get_ptr(k);
  }
  D at(int k) {
    assert(0 <= k && k < sz());
    return n->at(k);
  }
  int sz() { return n->sz; }
  D minv(int l, int r) { return n->minv(l, r); }
  void set(int k, D x) {
    n->set(k, x);
    return;
  }
  void tp() {
    n->tp();
    printf("\\n");
  }
};
template <class D>
typename AATree<D>::Node AATree<D>::last_d = AATree<D>::Node();
template <class D> typename AATree<D>::NP AATree<D>::last = &AATree<D>::last_d;

ll a[MN];
int main() {
  int n, q;
  cin >> n >> q;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  STree tr = STree(n, a);
  AATree<ll> atr(n, a);
  for (int i = 0; i < q; i++) {
    // tr.print();
    int x, y, z;
    cin >> x >> y >> z;
    if (x == 0) {
      int l = y, r = z;
      STree t0 = tr.split(r + 1);
      STree t1 = tr.split(r);
      STree t2 = tr.split(l);
      auto at0 = atr.split(r + 1);
      auto at1 = atr.split(r);
      auto at2 = atr.split(l);
      tr.merge(t1);
      tr.merge(t2);
      tr.merge(t0);
      atr.merge(at1);
      atr.merge(at2);
      atr.merge(at0);
    } else if (x == 1) {
      int l = y, r = z;
      r++;
      printf("%lld\\n", atr.minv(l, r));
      //            printf("%lld %lld\\n", tr.get(l, r), atr.minv(l, r));
    } else {
      int l = y, val = z;
      atr.set(l, val);
      tr.set(l, val);
    }
    // atr.tp();
  }
  return 0;
}