class SegmentTree
	def initialize(a, l = 1, r = a.size)
		@range_min = l
		@range_max = r
		if l == r
			@min = a[l-1]
		else
			c = (l + r) / 2
			@left_child = self.class.new(a, l, c)
			@right_child = self.class.new(a, c+1, r)
			@min = @left_child.min < @right_child.min ? @left_child.min : @right_child.min 
		end
	end

	attr_reader :range_min, :range_max

	def update(i, v)
		if @range_min == @range_max
			@min = v
		else 
			force if @unforced
			if i <= @left_child.range_max
				@left_child.update(i, v)
			else
				@right_child.update(i, v)
			end
			@min = @left_child.min < @right_child.min ? @left_child.min : @right_child.min 
		end
	end

	def rotate(x, y)

		if x == @range_min && y == @range_max
			@unforced = true
		else
			force if @unforced
			if y <= @left_child.range_max
				@left_child.rotate(x, y)	
			elsif @right_child.range_min <= x
				@right_child.rotate(x, y)
			else
				i = @left_child.range_max
				s = min(i, i)
				t = min(y, y)
				update(i, t)
				update(y, s)
				@left_child.rotate(x, i)
				@right_child.rotate(i+1, y)
			end
		end
	end

	def force
		@unforced = false
		i = @left_child.range_max
		s = @left_child.min(i, i)
		t = @right_child.min(@range_max, @range_max)
		@left_child.update(i, t)
		@right_child.update(@range_max, s)
		@left_child.rotate(@range_min, i)
		@right_child.rotate(i+1, @range_max)
	end

	def min(x = @range_min, y = @range_max)
		return Float::INFINITY if x > y

		if x == @range_min && y == @range_max
			@min
		else
			force if @unforced
			lr = @left_child.range_max
			l_min = @left_child.min(x, lr < y ? lr : y)
			rl = @right_child.range_min
			r_min = @right_child.min(rl > x ? rl : x, y)
			l_min < r_min ? l_min : r_min
		end
	end
end

N, Q = gets.split.map(&:to_i)
A = (1..N).map{ gets.to_i }
st = SegmentTree.new(A)
 
Q.times {
	q, x, y = gets.split.map(&:to_i)
	case q
	when 0
		st.rotate(x+1, y+1)
	when 1
		puts st.min(x+1, y+1)
	when 2
		st.update(x+1, y)
	end
}