import core.stdc.stdio;
import std.typecons;
import std.typetuple;
import std.algorithm;

alias TypeTuple tie;

struct Node{
	int l=-1,r=-1,p=-1,s,v,m;
}
Node[] d;

void Update(int x){
	with(d[x]){
		s=1;
		m=v;
		if(l>=0){
			m=min(m,d[l].m);
			s+=d[l].s;
		}
		if(r>=0){
			m=min(m,d[r].m);
			s+=d[r].s;
		}
	}
}

int Pos(int x){
	with(d[x]){
		if(p>=0&&d[p].l==x) return -1;
		if(p>=0&&d[p].r==x) return 1;
		return 0;
	}
}

void Rotate(int x){
	with(d[x]){
		int q=p,c;
		if(x.Pos==1){
			c=l;
			l=p;
			d[p].r=c;
		}else{
			c=r;
			r=p;
			d[p].l=c;
		}
		if(c>=0) d[c].p=p;
		p=d[p].p;
		d[q].p=x;
		if(p>=0&&d[p].l==q) d[p].l=x;
		if(p>=0&&d[p].r==q) d[p].r=x;
		q.Update;
		x.Update;
	}
}

void Splay(int x){
	with(d[x]){
		while(p>=0){
			int a=x.Pos*p.Pos;
			if(!a)
				x.Rotate;
			else if(a==1){
				p.Rotate;
				x.Rotate;
			}else{
				x.Rotate;
				x.Rotate;
			}
		}
	}
}

int Idx(int x,int i){
	with(d[x]){
		int ls=l>=0?d[l].s:0;
		if(i==ls){
			x.Splay();
			return x;
		}else if(i<ls)
			return l.Idx(i);
		else
			return r.Idx(i-ls-1);
	}
}

auto Split(int x,bool con){
	assert(x>=0);
	assert(!x.Pos);
	with(d[x]){
		int c;
		if(con){
			c=l;
			if(c>=0){
				d[c].p=-1;
				l=-1;
				x.Update;
			}
			return tuple(c,x);
		}else{
			c=r;
			if(c>=0){
				d[c].p=-1;
				r=-1;
				x.Update;
			}
			return tuple(x,c);
		}
	}
}

int Merge(int a,int b){
	if(a<0) return b;
	if(b<0) return a;
	b.Splay;
	while(d[b].l>=0) b=d[b].l;
	b.Splay;
	a.Splay;
	d[b].l=a;
	d[a].p=b;
	b.Update;
	return b;
}

void main(){
	int n,q;
	scanf("%d%d",&n,&q);
	d=new Node[n];
	foreach(i;0..n){
		scanf("%d",&d[i].v);
		if(i){
			d[i].l=i-1;
			d[i-1].p=i;
		}
		i.Update;
	}
	int r=n-1;
	foreach(_;0..q){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		int t1,t2,t3,t4;
		if(x==0){
			tie!(t3,t4)=Split(r.Idx(z),false);
			tie!(t2,t3)=Split(t3.Idx(z),true);
			tie!(t1,t2)=Split(t2.Idx(y),true);
			r=t1.Merge(t3).Merge(t2).Merge(t4);
		}else if(x==1){
			tie!(t2,t3)=Split(r.Idx(z),false);
			tie!(t1,t2)=Split(t2.Idx(y),true);
			printf("%d\n",d[t2].m);
			r=t1.Merge(t2).Merge(t3);
		}else if(x==2){
			r=r.Idx(y);
			d[r].v=z;
			r.Update;
		}
	}
}