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

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

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);
}

Measured memory_bytes: 10588