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

#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;

#include <algorithm>
#include <memory>
#include <vector>

const int INF = 1000000000;

struct Node {
  int value;
  double priority;
  std::unique_ptr<Node> left_child, right_child;
  int size;
  int sum;
  Node(int v, double p)
      : value(v), priority(p), left_child(nullptr), right_child(nullptr),
        size(1), sum(v) {}
};

int size(std::unique_ptr<Node> &node) { return node ? node->size : 0; }
int sum(std::unique_ptr<Node> &node) { return node ? node->sum : INF; }
std::unique_ptr<Node> update(std::unique_ptr<Node> &node) {
  node->size = size(node->left_child) + size(node->right_child) + 1;
  node->sum =
      std::min({sum(node->left_child), sum(node->right_child), node->value});
  return std::move(node);
}
std::unique_ptr<Node> merge(std::unique_ptr<Node> &left,
                            std::unique_ptr<Node> &right) {
  if (!left || !right)
    return std::move(left ? left : right);
  if (left->priority > right->priority) {
    left->right_child = merge(left->right_child, right);
    return update(left);
  } else {
    right->left_child = merge(left, right->left_child);
    return update(right);
  }
}
std::vector<std::unique_ptr<Node>> split(std::unique_ptr<Node> &node, int k) {
  std::vector<std::unique_ptr<Node>> result(2);
  if (!node)
    return result;
  if (k <= size(node->left_child)) {
    result = split(node->left_child, k);
    node->left_child = std::move(result[1]);
    result[1] = update(node);
    return result;
  } else {
    result = split(node->right_child, k - size(node->left_child) - 1);
    node->right_child = std::move(result[0]);
    result[0] = update(node);
    return result;
  }
  return result;
}
std::unique_ptr<Node> insert(std::unique_ptr<Node> &node, int k, int v) {
  auto t = split(node, k);
  auto n = std::unique_ptr<Node>(new Node(v, rand()));
  t[0] = merge(t[0], n);
  return merge(t[0], t[1]);
}
std::unique_ptr<Node> erase(std::unique_ptr<Node> &node, int k) {
  auto t1 = split(node, k);
  auto t2 = split(t1[1], 1);
  return merge(t1[0], t2[1]);
}
int query(std::unique_ptr<Node> &node, int left, int right) {
  if (!node)
    return INF;
  if (right < 0 || size(node) < left)
    return INF;
  if (left <= 0 && size(node) <= right)
    return node->sum;

  int result = min(query(node->left_child, left, right),
                   query(node->right_child, left - size(node->left_child) - 1,
                         right - size(node->left_child) - 1));
  if (left <= size(node->left_child) && size(node->left_child) <= right)
    return min(result, node->value);
  return result;
}

int find(std::unique_ptr<Node> &node, int k) {
  if (k < size(node->left_child))
    return find(node->left_child, k);
  if (k == size(node->left_child))
    return node->value;
  return find(node->right_child, k - size(node->left_child) - 1);
}
void traverse(const std::unique_ptr<Node> &node, int depth) {
  cout << depth << ": " << node->size << " : " << node->value << " : "
       << node->sum << endl;
  if (node->left_child)
    traverse(node->left_child, depth + 1);
  if (node->right_child)
    traverse(node->right_child, depth + 1);
}

int main() {
  int n, q;
  cin >> n >> q;

  unique_ptr<Node> treap;
  for (int i = 0; i < n; ++i) {
    int a;
    cin >> a;
    treap = insert(treap, i, a);
  }

  for (int i = 0; i < q; ++i) {
    int x, y, z;
    cin >> x >> y >> z;
    if (x == 0) {
      // circular shift
      auto t1 = split(treap, z + 1);
      auto t2 = split(t1[0], z);
      auto t3 = split(t2[0], y);
      treap = merge(t3[0], t2[1]);
      treap = merge(treap, t3[1]);
      treap = merge(treap, t1[1]);
      //             cout<<"+"<<endl;
      //             for(int i = 0; i < n; ++i)cout<<find(treap, i)<<endl;
    } else if (x == 1) {
      // find
      cout << query(treap, y, z) << endl;
    } else {
      // update
      treap = erase(treap, y);
      treap = insert(treap, y, z);
    }
  }
  //     traverse(treap, 0);
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <vector>

const int INF = INT_MAX;
const int NIL = -1;

int leftMostBit(int x) {
  if (x == 0)
    return 0;
  x = (x & 0x55555555) << 1 | (x >> 1) & 0x55555555;
  x = (x & 0x33333333) << 2 | (x >> 2) & 0x33333333;
  x = (x & 0x0f0f0f0f) << 4 | (x >> 4) & 0x0f0f0f0f;
  x = (x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24);
  int deBruijnSequence[32] = {0,  1,  23, 2,  29, 24, 19, 3,  30, 27, 25,
                              11, 20, 8,  4,  13, 31, 22, 28, 18, 26, 10,
                              7,  12, 21, 17, 9,  6,  16, 5,  15, 14};
  return 31 - deBruijnSequence[((x & -x) * 0x076be629U) >> 27];
}

class RangeMinimumQuery {
  int size_;
  std::vector<int> node_;

  int parent(int node) const { return node == 0 ? NIL : (node - 1) >> 1; }
  int left_child(int node) const { return (node << 1) + 1; }
  int right_child(int node) const { return (node << 1) + 2; }
  int query(int a, int b, int k, int l, int r) const {
    if (b < l || r < a)
      return INF;
    if (a <= l && r <= b)
      return node_[k];
    int vl = query(a, b, left_child(k), l, (l + r) / 2);
    int vr = query(a, b, right_child(k), (l + r) / 2 + 1, r);
    return std::min(vl, vr);
  }

public:
  RangeMinimumQuery(int s) {
    size_ = 1 << leftMostBit(s);
    if (size_ != s)
      size_ <<= 1;
    node_ = std::vector<int>((size_ << 1) - 1, INF);
  }
  void update_values(int left, int right) {
    int l = left + size_ - 1;
    int r = right + size_ - 1;
    while ((l = parent(l)) != (r = parent(r))) {
      for (int i = l; i <= r; ++i)
        node_[i] = std::min(node_[left_child(i)], node_[right_child(i)]);
    }
    int i = l;
    node_[i] = std::min(node_[left_child(i)], node_[right_child(i)]);
    while ((i = parent(i)) != NIL)
      node_[i] = std::min(node_[left_child(i)], node_[right_child(i)]);
  }
  int find(int left, int right) {
    update_values(left, right);
    return query(left, right, 0, 0, size_ - 1);
  }
  void update(int index, int value) {
    int i = index + size_ - 1;
    node_[i] = value;
    //         while((i = parent(i)) != NIL) node_[i] =
    //         std::min(node_[left_child(i)], node_[right_child(i)]);
  }
  void circular_shift(int left, int right) {
    int l = left + size_ - 1;
    int r = right + size_ - 1;
    for (int i = r; l < i; --i)
      std::swap(node_[i], node_[i - 1]);
    //         while((l = parent(l)) != (r = parent(r))) {
    //             for(int i = l; i <= r; ++i) node_[i] =
    //             std::min(node_[left_child(i)], node_[right_child(i)]);
    //         }
  }
};

#include <iostream>
using namespace std;

int main() {
  int n, q;

  cin >> n >> q;
  RangeMinimumQuery st(n);
  for (int i = 0; i < n; ++i) {
    int a;
    cin >> a;
    st.update(i, a);
  }

  for (int i = 0; i < q; ++i) {
    int x, y, z;
    cin >> x >> y >> z;
    if (x == 0) {
      st.circular_shift(y, z);
    } else if (x == 1) {
      cout << st.find(y, z) << endl;
    } else {
      st.update(y, z);
    }
  }
}