Problem p00998 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

// RBST (平衡二分探索木)
// データ型・最大値用の単位元を指定して使う
// TODO: 使い方をまとめる (わすれるので)

inline uint32_t xor128() {
  static uint32_t x = 123456789;
  static uint32_t y = 362436069;
  static uint32_t z = 521288629;
  static uint32_t w = 88675123;
  uint32_t t;

  t = x ^ (x << 11);
  x = y;
  y = z;
  z = w;
  return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}

namespace rbt {
template <typename Type> struct node_t {
  Type val, sum, max_val, min_val;
  node_t<Type> *lch, *rch, *par;
  int cap;
  node_t(int val_)
      : val(val_), sum(val_), max_val(val_), min_val(val_), cap(1) {
    lch = rch = par = nullptr;
  }
};

// 扱う要素の型と、max, min に用いる単位元
// (どれと max, min とっても変わらないやつ)
template <typename Type, Type max_identity, Type min_identity> struct rbst {
  using RBST = rbst<Type, max_identity, min_identity>;

private:
  size_t size_;
  node_t<Type> *root;

  // 根の情報
  void eval(node_t<Type> *t) { root = t, size_ = t ? count(update(t)) : 0; }

  // 部分木の情報
  int count(node_t<Type> *t) { return t ? t->cap : 0; }
  Type sum(node_t<Type> *t) { return t ? t->sum : 0; }
  Type max_val(node_t<Type> *t) { return t ? t->max_val : max_identity; }
  Type min_val(node_t<Type> *t) { return t ? t->min_val : min_identity; }

  // 部分木に関する情報の再計算
  node_t<Type> *update(node_t<Type> *t, Type val = max_identity) {
    if (val != max_identity)
      t->val = val;
    t->cap = count(t->lch) + count(t->rch) + 1;
    t->sum = sum(t->lch) + sum(t->rch) + t->val;
    t->max_val = max({max_val(t->lch), max_val(t->rch), t->val});
    t->min_val = min({min_val(t->lch), min_val(t->rch), t->val});
    if (t->par)
      update(t->par);
    return t;
  }

public:
  node_t<Type> *merge(node_t<Type> *l, node_t<Type> *r) {
    if (!l || !r)
      return !l ? r : l;

    uint32_t rnd = xor128();
    double prob = (double)rnd / UINT_MAX;
    // fprintf(stderr, "%.12f\\n", prob);
    int N = count(l), M = count(r);
    if (prob < (double)N / (N + M)) {
      if (l->rch)
        l->rch->par = nullptr;
      node_t<Type> *child = merge(l->rch, r);
      l->rch = child;
      if (child)
        child->par = l;
      return update(l);
    } else {
      if (r->lch)
        r->lch->par = nullptr;
      node_t<Type> *child = merge(l, r->lch);
      r->lch = child;
      if (child)
        child->par = r;
      return update(r);
    }
  }

  // 場所 k で split  [0, k), [k, n)
  pair<node_t<Type> *, node_t<Type> *> split(node_t<Type> *t, int k) {
    if (t == nullptr)
      return make_pair(nullptr, nullptr);

    if (k <= count(t->lch)) {
      if (t->lch)
        t->lch->par = nullptr;
      pair<node_t<Type> *, node_t<Type> *> s = split(t->lch, k);
      t->lch = s.second;
      if (s.second)
        s.second->par = t;
      return make_pair(s.first, update(t));
    } else {
      if (t->rch)
        t->rch->par = nullptr;
      pair<node_t<Type> *, node_t<Type> *> s =
          split(t->rch, k - count(t->lch) - 1);
      t->rch = s.first;
      if (s.first)
        s.first->par = t;
      return make_pair(update(t), s.second);
    }
  }

  node_t<Type> *insert(node_t<Type> *t, int k, Type val) {
    pair<node_t<Type> *, node_t<Type> *> lr = split(t, k);
    node_t<Type> *newElem = new node_t<Type>(val);

    node_t<Type> *res = merge(lr.first, newElem);
    res = merge(res, lr.second);
    return res;
  }

  node_t<Type> *erase(node_t<Type> *t, int k) {
    pair<node_t<Type> *, node_t<Type> *> lr2 = split(t, k + 1);

    t = lr2.first;
    pair<node_t<Type> *, node_t<Type> *> lr1 = split(t, k);

    node_t<Type> *res = merge(lr1.first, lr2.second);
    return res;
  }

  // k 番目の要素 (0-indexed)
  node_t<Type> *kth_node(node_t<Type> *t, int k) {
    assert(k < count(t));

    if (count(t->lch) >= k + 1) {
      return kth_node(t->lch, k);
    } else if (count(t->lch) + 1 == k + 1) {
      return t;
    } else {
      return kth_node(t->rch, k - count(t->lch) - 1);
    }
  }

  Type kth_number(node_t<Type> *t, int k) {
    assert(k < size());
    return kth_node(t, k)->val;
  }

  // lower bound (0-indexed)
  int lower_bound(node_t<Type> *t, Type val, int idx = 0) {
    if (t == nullptr)
      return idx;

    if (t->lch && t->lch->max_val >= val) {
      return lower_bound(t->lch, val, idx);
    }
    if (t->val >= val) {
      return idx + (count(t) - count(t->rch)) - 1;
    }
    if (t->rch && t->rch->max_val >= val) {
      return lower_bound(t->rch, val, idx + count(t->lch) + 1);
    }
    return idx + count(t);
  }

  // upper bound (0-indexed)
  int upper_bound(node_t<Type> *t, Type val, int idx = 0) {
    if (t == nullptr)
      return idx;
    if (t->lch && t->lch->max_val > val) {
      return upper_bound(t->lch, val, idx);
    }
    if (t->val > val) {
      return idx + (count(t) - count(t->rch)) - 1;
    }
    if (t->rch && t->rch->max_val > val) {
      return lower_bound(t->rch, val, idx + count(t->lch) + 1);
    }
    return idx + count(t);
  }

  int get_idx(node_t<Type> *t) {
    if (t->par == nullptr)
      return count(t->lch);
    else if (t->par->lch == t) {
      return get_idx(t->par) - count(t->rch) - 1;
    } else {
      return get_idx(t->par) + count(t->lch) + 1;
    }
  }

  // rmq を解く (minmax: 0 で最大、1 で最小)
  Type rmq_query(int a, int b, int l, int r, node_t<Type> *cur, int minmax) {
    Type identity = (minmax ? min_identity : max_identity);
    if (r <= a || b <= l || !cur)
      return identity;
    if (a <= l && r <= b)
      return (minmax ? cur->min_val : cur->max_val);
    // 答え (現在の頂点を入れることも)
    int idx = get_idx(cur), nl, nr;
    Type ans = (a <= idx && idx < b) ? cur->val : identity;

    auto get = [&](Type A, Type B) { return minmax ? min(A, B) : max(A, B); };

    // 左の子へ (右端が縮む)
    if (cur->lch) {
      nl = l, nr = r - 1 - count(cur->rch);
      ans = get(ans, rmq_query(a, b, nl, nr, cur->lch, minmax));
    }

    // 右の子へ (左端が縮む)
    if (cur->rch) {
      nl = l + 1 + count(cur->lch), nr = r;
      ans = get(ans, rmq_query(a, b, nl, nr, cur->rch, minmax));
    }
    return ans;
  }

  rbst() { size_ = 0, root = nullptr; }
  rbst(node_t<Type> *r) { eval(r); }
  node_t<Type> *get_root() { return root; }
  size_t size() { return size_; }
  bool empty() { return size_ == 0; }

  void insert(Type val, int k) { eval(insert(root, k, val)); }
  void erase(int k) { eval(erase(root, k)); }

  pair<RBST, RBST> split(int k) {
    pair<node_t<Type> *, node_t<Type> *> lr = split(root, k);
    return make_pair(RBST(lr.first), RBST(lr.second));
  }
  RBST merge(RBST l, RBST r) {
    eval(merge(l.get_root(), r.get_root()));
    return RBST(root);
  }
  node_t<Type> *kth_node(int k) { return kth_node(root, k); }
  Type kth_number(int k) { return kth_number(root, k); }
  int lower_bound(Type val) { return lower_bound(root, val); }
  int upper_bound(Type val) { return upper_bound(root, val); }
  void update(Type val, int k) {
    node_t<Type> *node = kth_node(k);
    update(node, val);
  }
  bool find(Type val) {
    int idx = lower_bound(val);
    if (idx >= size_)
      return false;
    return kth_number(idx) == val;
  }

  Type find_min(int l, int r) { return rmq_query(l, r, 0, size(), root, 1); }
  Type find_max(int l, int r) { return rmq_query(l, r, 0, size(), root, 0); }

  void dump_array() {
    for (int i = 0; i < size(); i++) {
      fprintf(stderr, "%d ", kth_number(i));
    }
    fprintf(stderr, "\\n");
  }

  // みさわさんの根付き木と多分同じフォーマット？
  void dump_tree(node_t<Type> *t) {
    if (t == nullptr)
      return;
    if (t->lch) {
      fprintf(stderr, "(");
      dump_tree(t->lch);
      fprintf(stderr, ")");
    }
    fprintf(stderr, "[%d", t->val);
    if (t->par) {
      fprintf(stderr, "<%d>", t->par->val);
    } else {
      fprintf(stderr, "<NA>");
    }
    fprintf(stderr, "]");
    if (t->rch) {
      fprintf(stderr, "(");
      dump_tree(t->rch);
      fprintf(stderr, ")");
    }
  }
};

// 重複を許さない全順序集合
template <typename Type, Type max_identity, Type min_identity>
struct Set : public rbst<Type, max_identity, min_identity> {
public:
  using PRBST = rbst<Type, max_identity, min_identity>;
  bool empty() { return PRBST::size() == 0; }
  void insert(Type val) {
    if (PRBST::find(val))
      return;
    int idx = PRBST::lower_bound(val);
    PRBST::insert(val, idx);
  }

  void erase(Type val) {
    if (empty() || !PRBST::find(val))
      return;
    int idx = PRBST::lower_bound(val);
    PRBST::erase(idx);
  }
};

// TODO: multiset も書く
} // namespace rbt

using RB = rbt::rbst<int, -1, 1 << 28>;
int main() {
  int N, Q;
  cin >> N >> Q;

  RB rb;
  for (int i = 0; i < N; i++) {
    int val;
    cin >> val;
    rb.insert(val, i);
  }

  for (int i = 0; i < Q; i++) {
    int x, y, z;
    cin >> x >> y >> z;

    if (x == 0) {
      RB rb1, rb2, rb3, rb4;
      tie(rb3, rb4) = rb.split(z + 1);
      tie(rb2, rb3) = rb3.split(z);
      tie(rb1, rb2) = rb2.split(y);

      rb = rb.merge(rb1, rb3);
      rb = rb.merge(rb, rb2);
      rb = rb.merge(rb, rb4);
    }
    if (x == 1) {
      cout << rb.find_min(y, z + 1) << endl;
    }
    if (x == 2) {
      rb.update(z, y);
    }

    // rb.dump_array();
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

// RBST (平衡二分探索木)
// データ型・最大値用の単位元を指定して使う
// TODO: 使い方をまとめる (わすれるので)

inline uint32_t xor128() {
  static uint32_t x = 123456789;
  static uint32_t y = 362436069;
  static uint32_t z = 521288629;
  static uint32_t w = 88675123;
  uint32_t t;

  t = x ^ (x << 11);
  x = y;
  y = z;
  z = w;
  return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}

namespace rbt {
template <typename Type> struct node_t {
  Type val, sum, max_val, min_val;
  node_t<Type> *lch, *rch, *par;
  int cap;
  node_t(int val_)
      : val(val_), sum(val_), max_val(val_), min_val(val_), cap(1) {
    lch = rch = par = nullptr;
  }
};

// 扱う要素の型と、max, min に用いる単位元
// (どれと max, min とっても変わらないやつ)
template <typename Type, Type max_identity, Type min_identity> struct rbst {
  using RBST = rbst<Type, max_identity, min_identity>;

private:
  size_t size_;
  node_t<Type> *root;

  // 根の情報
  void eval(node_t<Type> *t) { root = t, size_ = t ? count(update(t)) : 0; }

  // 部分木の情報
  int count(node_t<Type> *t) { return t ? t->cap : 0; }
  Type sum(node_t<Type> *t) { return t ? t->sum : 0; }
  Type max_val(node_t<Type> *t) { return t ? t->max_val : max_identity; }
  Type min_val(node_t<Type> *t) { return t ? t->min_val : min_identity; }

  // 部分木に関する情報の再計算
  node_t<Type> *update(node_t<Type> *t, Type val = max_identity) {
    if (val != max_identity)
      t->val = val;
    t->cap = count(t->lch) + count(t->rch) + 1;
    t->sum = sum(t->lch) + sum(t->rch) + t->val;
    t->max_val = max({max_val(t->lch), max_val(t->rch), t->val});
    t->min_val = min({min_val(t->lch), min_val(t->rch), t->val});
    if (t->par)
      update(t->par);
    return t;
  }

public:
  node_t<Type> *merge(node_t<Type> *l, node_t<Type> *r) {
    if (!l || !r)
      return !l ? r : l;

    uint32_t rnd = xor128();
    double prob = rnd / UINT_MAX;
    int N = count(l), M = count(r);
    if (prob < (double)N / (N + M)) {
      if (l->rch)
        l->rch->par = nullptr;
      node_t<Type> *child = merge(l->rch, r);
      l->rch = child;
      if (child)
        child->par = l;
      return update(l);
    } else {
      if (r->lch)
        r->lch->par = nullptr;
      node_t<Type> *child = merge(l, r->lch);
      r->lch = child;
      if (child)
        child->par = r;
      return update(r);
    }
  }

  // 場所 k で split  [0, k), [k, n)
  pair<node_t<Type> *, node_t<Type> *> split(node_t<Type> *t, int k) {
    if (t == nullptr)
      return make_pair(nullptr, nullptr);

    if (k <= count(t->lch)) {
      if (t->lch)
        t->lch->par = nullptr;
      pair<node_t<Type> *, node_t<Type> *> s = split(t->lch, k);
      t->lch = s.second;
      if (s.second)
        s.second->par = t;
      return make_pair(s.first, update(t));
    } else {
      if (t->rch)
        t->rch->par = nullptr;
      pair<node_t<Type> *, node_t<Type> *> s =
          split(t->rch, k - count(t->lch) - 1);
      t->rch = s.first;
      if (s.first)
        s.first->par = t;
      return make_pair(update(t), s.second);
    }
  }

  node_t<Type> *insert(node_t<Type> *t, int k, Type val) {
    pair<node_t<Type> *, node_t<Type> *> lr = split(t, k);
    node_t<Type> *newElem = new node_t<Type>(val);

    node_t<Type> *res = merge(lr.first, newElem);
    res = merge(res, lr.second);
    return res;
  }

  node_t<Type> *erase(node_t<Type> *t, int k) {
    pair<node_t<Type> *, node_t<Type> *> lr2 = split(t, k + 1);

    t = lr2.first;
    pair<node_t<Type> *, node_t<Type> *> lr1 = split(t, k);

    node_t<Type> *res = merge(lr1.first, lr2.second);
    return res;
  }

  // k 番目の要素 (0-indexed)
  node_t<Type> *kth_node(node_t<Type> *t, int k) {
    assert(k < count(t));

    if (count(t->lch) >= k + 1) {
      return kth_node(t->lch, k);
    } else if (count(t->lch) + 1 == k + 1) {
      return t;
    } else {
      return kth_node(t->rch, k - count(t->lch) - 1);
    }
  }

  Type kth_number(node_t<Type> *t, int k) {
    assert(k < size());
    return kth_node(t, k)->val;
  }

  // lower bound (0-indexed)
  int lower_bound(node_t<Type> *t, Type val, int idx = 0) {
    if (t == nullptr)
      return idx;

    if (t->lch && t->lch->max_val >= val) {
      return lower_bound(t->lch, val, idx);
    }
    if (t->val >= val) {
      return idx + (count(t) - count(t->rch)) - 1;
    }
    if (t->rch && t->rch->max_val >= val) {
      return lower_bound(t->rch, val, idx + count(t->lch) + 1);
    }
    return idx + count(t);
  }

  // upper bound (0-indexed)
  int upper_bound(node_t<Type> *t, Type val, int idx = 0) {
    if (t == nullptr)
      return idx;
    if (t->lch && t->lch->max_val > val) {
      return upper_bound(t->lch, val, idx);
    }
    if (t->val > val) {
      return idx + (count(t) - count(t->rch)) - 1;
    }
    if (t->rch && t->rch->max_val > val) {
      return lower_bound(t->rch, val, idx + count(t->lch) + 1);
    }
    return idx + count(t);
  }

  int get_idx(node_t<Type> *t) {
    if (t->par == nullptr)
      return count(t->lch);
    else if (t->par->lch == t) {
      return get_idx(t->par) - count(t->rch) - 1;
    } else {
      return get_idx(t->par) + count(t->lch) + 1;
    }
  }

  // rmq を解く (minmax: 0 で最大、1 で最小)
  Type rmq_query(int a, int b, int l, int r, node_t<Type> *cur, int minmax) {
    Type identity = (minmax ? min_identity : max_identity);
    if (r <= a || b <= l || !cur)
      return identity;
    if (a <= l && r <= b)
      return (minmax ? cur->min_val : cur->max_val);
    // 答え (現在の頂点を入れることも)
    int idx = get_idx(cur), nl, nr;
    Type ans = (a <= idx && idx < b) ? cur->val : identity;

    auto get = [&](Type A, Type B) { return minmax ? min(A, B) : max(A, B); };

    // 左の子へ (右端が縮む)
    if (cur->lch) {
      nl = l, nr = r - 1 - count(cur->rch);
      ans = get(ans, rmq_query(a, b, nl, nr, cur->lch, minmax));
    }

    // 右の子へ (左端が縮む)
    if (cur->rch) {
      nl = l + 1 + count(cur->lch), nr = r;
      ans = get(ans, rmq_query(a, b, nl, nr, cur->rch, minmax));
    }
    return ans;
  }

  rbst() { size_ = 0, root = nullptr; }
  rbst(node_t<Type> *r) { eval(r); }
  node_t<Type> *get_root() { return root; }
  size_t size() { return size_; }
  bool empty() { return size_ == 0; }

  void insert(Type val, int k) { eval(insert(root, k, val)); }
  void erase(int k) { eval(erase(root, k)); }

  pair<RBST, RBST> split(int k) {
    pair<node_t<Type> *, node_t<Type> *> lr = split(root, k);
    return make_pair(RBST(lr.first), RBST(lr.second));
  }
  RBST merge(RBST l, RBST r) {
    eval(merge(l.get_root(), r.get_root()));
    return RBST(root);
  }
  node_t<Type> *kth_node(int k) { return kth_node(root, k); }
  Type kth_number(int k) { return kth_number(root, k); }
  int lower_bound(Type val) { return lower_bound(root, val); }
  int upper_bound(Type val) { return upper_bound(root, val); }
  void update(Type val, int k) {
    node_t<Type> *node = kth_node(k);
    update(node, val);
  }
  bool find(Type val) {
    int idx = lower_bound(val);
    if (idx >= size_)
      return false;
    return kth_number(idx) == val;
  }

  Type find_min(int l, int r) { return rmq_query(l, r, 0, size(), root, 1); }
  Type find_max(int l, int r) { return rmq_query(l, r, 0, size(), root, 0); }

  void dump_array() {
    for (int i = 0; i < size(); i++) {
      fprintf(stderr, "%d ", kth_number(i));
    }
    fprintf(stderr, "\\n");
  }

  // みさわさんの根付き木と多分同じフォーマット？
  void dump_tree(node_t<Type> *t) {
    if (t == nullptr)
      return;
    if (t->lch) {
      fprintf(stderr, "(");
      dump_tree(t->lch);
      fprintf(stderr, ")");
    }
    fprintf(stderr, "[%d", t->val);
    if (t->par) {
      fprintf(stderr, "<%d>", t->par->val);
    } else {
      fprintf(stderr, "<NA>");
    }
    fprintf(stderr, "]");
    if (t->rch) {
      fprintf(stderr, "(");
      dump_tree(t->rch);
      fprintf(stderr, ")");
    }
  }
};

// 重複を許さない全順序集合
template <typename Type, Type max_identity, Type min_identity>
struct Set : public rbst<Type, max_identity, min_identity> {
public:
  using PRBST = rbst<Type, max_identity, min_identity>;
  bool empty() { return PRBST::size() == 0; }
  void insert(Type val) {
    if (PRBST::find(val))
      return;
    int idx = PRBST::lower_bound(val);
    PRBST::insert(val, idx);
  }

  void erase(Type val) {
    if (empty() || !PRBST::find(val))
      return;
    int idx = PRBST::lower_bound(val);
    PRBST::erase(idx);
  }
};

// TODO: multiset も書く
} // namespace rbt

using RB = rbt::rbst<int, -1, 1 << 28>;
int main() {
  int N, Q;
  cin >> N >> Q;

  RB rb;
  for (int i = 0; i < N; i++) {
    int val;
    cin >> val;
    rb.insert(val, i);
  }

  for (int i = 0; i < Q; i++) {
    int x, y, z;
    cin >> x >> y >> z;

    if (x == 0) {
      RB rb1, rb2, rb3, rb4;
      tie(rb3, rb4) = rb.split(z + 1);
      tie(rb2, rb3) = rb3.split(z);
      tie(rb1, rb2) = rb2.split(y);

      rb = rb.merge(rb1, rb3);
      rb = rb.merge(rb, rb2);
      rb = rb.merge(rb, rb4);
    }
    if (x == 1) {
      cout << rb.find_min(y, z + 1) << endl;
    }
    if (x == 2) {
      rb.update(z, y);
    }

    // rb.dump_array();
  }
  return 0;
}