#include <bits/stdc++.h>
using namespace std;
using lint = long long;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;

template<class Z> Z rng(Z a, Z b) {
  static mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
  return uniform_int_distribution<Z>(a, b - 1)(mt);
}
namespace RandomizedBinarySearchTree {
  using T = int;
  static T op(const T& a, const T& b) { return min(a, b); }
  static constexpr T e() { return 2e9; }
  using U = char;
  static void ap(const U& f, T& a) {}
  static void cp(const U& g, U& f) {}
  static constexpr U id() { return 0; }
  static T op(const T& a, const T& b, const T& c) { return op(op(a, b), c); }

  struct Node;
  using Tree = Node*;
  struct Node {
    int sz = 0, h = 0;
    T val = e(), acc = e();
    U laz = id();
    bool rev = false;
    Tree lch = nullptr, rch = nullptr;
  };
  Tree nil = new Node();

  void apply(Tree t, const U& f) {
    ap(f, t->val);
    ap(f, t->acc);
    cp(f, t->laz);
  }
  void reverse(Tree t) {
    swap(t->lch, t->rch);
    t->rev ^= true;
  }
  void push(Tree t) {
    if (!(t->laz == id())) {
      apply(t->lch, t->laz);
      apply(t->rch, t->laz);
      t->laz = id();
    }
    if (t->rev) {
      reverse(t->lch);
      reverse(t->rch);
      t->rev = false;
    }
  }
  Tree update(Tree t) {
    t->sz = t->lch->sz + 1 + t->rch->sz;
    t->h = max(t->lch->h, t->rch->h) + 1;
    t->acc = op(t->lch->acc, t->val, t->rch->acc);
    return t;
  }
  Tree make(const T& val, Tree lch = nil, Tree rch = nil) {
    Tree t = new Node();
    t->val = val, t->lch = lch, t->rch = rch;
    return update(t);
  }

  template<class Itr> Tree build(Itr first, Itr last) {
    int n = distance(first, last);
    if (!n) return nil;
    Itr middle = next(first, n >> 1);
    return make(*middle, build(first, middle), build(next(middle), last));
  }
  template<class Itr> Itr dump(Tree t, Itr res) {
    if (t == nil) return res;
    push(t);
    res = dump(t->lch, res);
    *res++ = t->val;
    return dump(t->rch, res);
  }
  Tree rebuild(Tree t) {
    V<T> v(t->sz);
    dump(t, begin(v));
    return build(begin(v), end(v));
  }

  Tree merge(Tree l, Tree r) {
    if (l == nil) return r;
    if (r == nil) return l;
    if (rng(0, l->sz + r->sz) < l->sz) {
      push(l);
      l->rch = merge(l->rch, r);
      return update(l);
    } else {
      push(r);
      r->lch = merge(l, r->lch);
      return update(r);
    }
  }
  Tree merge(Tree l, Tree m, Tree r) { return merge(merge(l, m), r); }
  pair<Tree, Tree> split(Tree t, int i) {
    assert(0 <= i and i <= t->sz);
    if (t == nil) return {nil, nil};
    push(t);
    if (i <= t->lch->sz) {
      Tree l;
      tie(l, t->lch) = split(t->lch, i);
      return {l, update(t)};
    } else {
      Tree r;
      tie(t->rch, r) = split(t->rch, i - t->lch->sz - 1);
      return {update(t), r};
    }
  }
  tuple<Tree, Tree, Tree> split(Tree t, int l, int r) {
    assert(0 <= l and l <= r and r <= t->sz);
    Tree lt, mt, rt;
    tie(lt, rt) = split(t, r);
    tie(lt, mt) = split(lt, l);
    return make_tuple(lt, mt, rt);
  }

  Tree insert(Tree t, int i, const T& a) {
    assert(0 <= i and i <= t->sz);
    Tree l, r;
    tie(l, r) = split(t, i);
    return merge(l, make(a), r);
  }
  Tree erase(Tree t, int i) {
    assert(0 <= i and i < t->sz);
    Tree l, r;
    tie(l, ignore, r) = split(t, i, i + 1);
    return merge(l, r);
  }

  T get(Tree t, int i) {
    assert(0 <= i and i < t->sz);
    if (i == t->lch->sz) return t->val;
    push(t);
    if (i < t->lch->sz) return get(t->lch, i);
    else return get(t->rch, i - t->lch->sz - 1);
  }
  void set(Tree t, int i, const T& a) {
    assert(0 <= i and i < t->sz);
    push(t);
    if (i == t->lch->sz) {
      t->val = a;
    } else if (i < t->lch->sz) {
      set(t->lch, i, a);
    } else {
      set(t->rch, i - t->lch->sz - 1, a);
    }
    update(t);
  }

  T acc(Tree t, int l, int r) {
    if (l <= 0 and t->sz <= r) return t->acc;
    push(t);
    T resl = l < t->lch->sz ? acc(t->lch, l, r) : e();
    T resr = t->lch->sz + 1 < r ? acc(t->rch, l - t->lch->sz - 1, r - t->lch->sz - 1) : e();
    T resm = l <= t->lch->sz and t->lch->sz < r ? t->val : e();
    return op(resl, resm, resr);
  }
  void act(Tree t, int l, int r, const U& f) {
    if (l <= 0 and t->sz <= r) {
      apply(t, f);
      return;
    }
    push(t);
    if (l < t->lch->sz) act(t->lch, l, r, f);
    if (t->lch->sz + 1 < r) act(t->rch, l - t->lch->sz - 1, r - t->lch->sz - 1, f);
    if (l <= t->lch->sz and t->lch->sz < r) ap(f, t->val);
    update(t);
  }
  Tree reverse(Tree t, int l, int r) {
    Tree lt, mt, rt;
    tie(lt, mt, rt) = split(t, l, r);
    reverse(mt);
    return merge(lt, mt, rt);
  }

  int lower_bound(Tree t, const T& a) {
    if (t == nil) return 0;
    push(t);
    if (t->val < a) return t->lch->sz + 1 + lower_bound(t->rch, a);
    else return lower_bound(t->lch, a);
  }
  int upper_bound(Tree t, const T& a) {
    if (t == nil) return 0;
    push(t);
    if (a < t->val) return upper_bound(t->lch, a);
    else return t->lch->sz + 1 + upper_bound(t->rch, a);
  }
  int count(Tree t, const T& a) { return upper_bound(t, a) - lower_bound(t, a); }
  Tree set_insert(Tree t, const T& a, bool multi = true) {
    if (!multi and count(t, a)) return t;
    return insert(t, lower_bound(t, a), a);
  }
  Tree set_erase(Tree t, const T& a) {
    assert(count(t, a));
    return erase(t, lower_bound(t, a));
  }
}
namespace RBST = RandomizedBinarySearchTree;

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);
  int n, q; cin >> n >> q;
  V<> a(n); for (auto&& e : a) cin >> e;
  auto t = RBST::build(begin(a), end(a));

  while (q--) {
    int tp; cin >> tp;
    if (!tp) {
      int l, r; cin >> l >> r, ++r;
      RBST::Tree lt, mt, rt;
      tie(lt, mt, rt) = split(t, l, r);
      RBST::Tree mlt, mrt;
      tie(mlt, mrt) = split(mt, mt->sz - 1);
      t = merge(lt, merge(mrt, mlt), rt);
    } else if (tp == 1) {
      int l, r; cin >> l >> r, ++r;
      cout << acc(t, l, r) << '\n';
    } else {
      int i, x; cin >> i >> x;
      RBST::set(t, i, x);
    }
    if (t->h >= 100) t = rebuild(t);
  }
}


Measured memory_bytes: 13120