using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; public class ABC { // long[] sp = Console.ReadLine().Split().Select(long .Parse).ToArray(); // int[] sp = Console.ReadLine().Split().Select(int.Parse).ToArray(); // int N = int.Parse(Console.ReadLine()); //CompLib.Collections.PriorityQueue public static void Main() { int N=0, Q=0; new readint(ref N, ref Q); int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray(); var segTree = new Segtree>(200001, (i, j) => new Tuple(Math.Min(i.Item1, j.Item1), (i.Item1 > j.Item1) ? j.Item2 : i.Item2), new Tuple(int.MaxValue, 0)); for (int i = 1; i <= a.Length; i++) { segTree.update(i, new Tuple(a[i-1],i)); } for (int i = 0; i < Q; i++) { int[] query = Console.ReadLine().Split().Select(int.Parse).ToArray(); if (query[0] == 1) { var left = segTree.look(query[1]); var right = segTree.look(query[2]); var left2 = left.Item2; var right2 = right.Item2; segTree.update(query[1], new Tuple(right.Item1, left.Item2)); segTree.update(query[2], new Tuple(left.Item1, right.Item2)); } else { var output = segTree.run(query[1], query[2]+1); Console.WriteLine(output.Item2); } } } } class readint { public readint(ref int i) { i = int.Parse(Console.ReadLine()); } public readint(ref int a, ref int b) { int[] sp = Console.ReadLine().Split().Select(int.Parse).ToArray(); a = sp[0]; b = sp[1]; } public readint(ref int a, ref int b,ref int c) { int[] sp = Console.ReadLine().Split().Select(int.Parse).ToArray(); a = sp[0]; b = sp[1]; c = sp[2]; } public readint(ref int a, ref int b,ref int c,ref int d) { int[] sp = Console.ReadLine().Split().Select(int.Parse).ToArray(); a = sp[0]; b = sp[1]; c = sp[2]; d = sp[3]; } } class readlong { public readlong(ref long i) { i = long.Parse(Console.ReadLine()); } public readlong(ref long a, ref long b) { long[] sp = Console.ReadLine().Split().Select(long.Parse).ToArray(); a = sp[0]; b = sp[1]; } public readlong(ref long a, ref long b, ref long c) { long[] sp = Console.ReadLine().Split().Select(long.Parse).ToArray(); a = sp[0]; b = sp[1]; c = sp[2]; } public readlong(ref long a, ref long b, ref long c, ref long d) { long[] sp = Console.ReadLine().Split().Select(long.Parse).ToArray(); a = sp[0]; b = sp[1]; c = sp[2]; d = sp[3]; } } class Util { public static long GCD(long a, long b) { if (a < b) swap(ref a, ref b); if (a % b == 0) return b; return GCD(b, a % b); } public static int GCD(int a, int b) { if (a < b) swap(ref a, ref b); if (a % b == 0) return b; return GCD(b, a % b); } public static void swap(ref T a, ref T b) { T temp = b; b = a; a = temp; } public static long LCM(long a, long b) { return a * b / GCD(a, b); } public static long LCM(int a, int b) { return Math.BigMul(a, b) / GCD(a, b); } public static int M = (int)(Math.Pow(10, 9)) + 7; private static int[] factorial_modM; public static int Multiple_modM(int a, int b) { return (int)(Math.BigMul(a, b) % M); } public static void factorial_modM_Prepare(int n) { factorial_modM = new int[n + 1]; factorial_modM[0] = 1; for (int i = 1; i <= n; ++i) { factorial_modM[i] = Multiple_modM(factorial_modM[i - 1], i); } } public static int Factorial(int n) { return factorial_modM[n]; } public static int Pow(int a, int m) { switch (m) { case 0: return 1; case 1: return a; default: int p1 = Pow(a, m / 2); int p2 = Multiple_modM(p1, p1); return ((m % 2) == 0) ? p2 : Multiple_modM(p2, a); } } public static int Div(int a, int b) { return Multiple_modM(a, Pow(b, M - 2)); } public static int nCr_modM(int n, int r) { if (n < r) { return 0; } if (n == r) { return 1; } int res = Factorial(n); res = Div(res, Factorial(r)); res = Div(res, Factorial(n - r)); return res; } } class UnionFind { public int tree_height; public UnionFind parent; public T item { get; private set; } public UnionFind(T item) { tree_height = 0; parent = this; } public UnionFind FindAdam() { if (parent == this) return this; else { UnionFind ParentOfParent = parent.FindAdam(); parent = ParentOfParent;//縦長な構成をつなぎ直している return ParentOfParent; } } public static void Unite(UnionFind a, UnionFind b) { UnionFind ParentOfA = a.FindAdam(); UnionFind ParentOfB = b.FindAdam(); if (ParentOfA.tree_height < ParentOfB.tree_height) { ParentOfA.parent = ParentOfB; ParentOfB.tree_height = Math.Max(ParentOfA.tree_height + 1, ParentOfB.tree_height); } else { ParentOfB.parent = ParentOfA; ParentOfA.tree_height = Math.Max(ParentOfB.tree_height + 1, ParentOfA.tree_height); } } } //Treap 平衡二分木 class Treap where T : IComparable { private class Node { private static Random g_rand = new Random(); private readonly int m_rank = g_rand.Next(); private readonly T m_value; private Node m_lch; private Node m_rch; private int m_count; public Node(T value) { m_value = value; m_count = 1; } private static int Count(Node node) { return (node != null) ? node.m_count : 0; } private Node Update() { m_count = Count(m_lch) + Count(m_rch) + 1; return this; } public static Node Merge(Node a, Node b) { if (a == null) { return b; } if (b == null) { return a; } if (a.m_rank < b.m_rank) { a.m_rch = Merge(a.m_rch, b); return a.Update(); } else { b.m_lch = Merge(a, b.m_lch); return b.Update(); } } public static Tuple Split(Node t, int k) { if (t == null) { return new Tuple(null, null); } if (k <= Count(t.m_lch)) { var pair = Split(t.m_lch, k); t.m_lch = pair.Item2; return new Tuple(pair.Item1, t.Update()); } else { var pair = Split(t.m_rch, k - Count(t.m_lch) - 1); t.m_rch = pair.Item1; return new Tuple(t.Update(), pair.Item2); } } public int FindIndex(T value) { int L = Count(m_lch); if (value.CompareTo(m_value) < 0) { return (m_lch != null) ? m_lch.FindIndex(value) : 0; } else if (value.CompareTo(m_value) > 0) { return (m_rch != null) ? m_rch.FindIndex(value) + L + 1 : L + 1; } else { return L; } } public T this[int i] { get { int L = Count(m_lch); if (i < L) { return m_lch[i]; } else if (i > L) { return m_rch[i - L - 1]; } else { return m_value; } } } } private Node node; public void Insert(T value) { if (node != null) { int k = node.FindIndex(value); var pair = Node.Split(node, k); node = Node.Merge(Node.Merge(pair.Item1, new Node(value)), pair.Item2); } else { node = new Node(value); } } public int FindIndex(T value) { return node.FindIndex(value); } public T this[int i] { get { return node[i]; } } } static class Permutation { private static void Search(List perms, Stack stack, T[] a) { int N = a.Length; if (N == 0) { perms.Add(stack.Reverse().ToArray()); } else { var b = new T[N - 1]; Array.Copy(a, 1, b, 0, N - 1); for (int i = 0; i < a.Length; ++i) { stack.Push(a[i]); Search(perms, stack, b); if (i < b.Length) { b[i] = a[i]; } stack.Pop(); } } } public static IEnumerable All(IEnumerable src) { var perms = new List(); Search(perms, new Stack(), src.ToArray()); return perms; } } namespace CompLib.Collections { #region PriorityQueue /// /// 指定した型のインスタンスを最も価値が低い順に取り出すことが可能な可変サイズのコレクションを表します. /// /// 優先度付きキュー内の要素の型を指定します. /// 内部的にはバイナリヒープによって実装されています. public class PriorityQueue { readonly List heap = new List(); readonly Comparison cmp; /// /// デフォルトの比較子を使用してインスタンスを初期化します. /// /// この操作は O(1) で実行されます. public PriorityQueue() { cmp = Comparer.Default.Compare; } /// /// デリゲートで表されるような比較関数を使用してインスタンスを初期化します. /// /// /// この操作は O(1) で実行されます. public PriorityQueue(Comparison comparison) { cmp = comparison; } /// /// 指定された比較子を使用してインスタンスを初期化します. /// /// /// この操作は O(1) で実行されます. public PriorityQueue(IComparer comparer) { cmp = comparer.Compare; } /// /// 優先度付きキューに要素を追加します. /// /// 優先度付きキューに追加される要素 /// 最悪計算量 O(log N) で実行されます. public void Enqueue(T item) { var pos = heap.Count; heap.Add(item); while (pos > 0) { var par = (pos - 1) / 2; if (cmp(heap[par], item) <= 0) break; heap[pos] = heap[par]; pos = par; } heap[pos] = item; } /// /// 優先度付きキューから最も価値が低い要素を削除し,返します. /// /// 優先度付きキューから削除された要素. /// 最悪計算量 O(log N) で実行されます. public T Dequeue() { var ret = heap[0]; var pos = 0; var x = heap[heap.Count - 1]; while (pos * 2 + 1 < heap.Count - 1) { var lch = pos * 2 + 1; var rch = pos * 2 + 2; if (rch < heap.Count - 1 && cmp(heap[rch], heap[lch]) < 0) lch = rch; if (cmp(heap[lch], x) >= 0) break; heap[pos] = heap[lch]; pos = lch; } heap[pos] = x; heap.RemoveAt(heap.Count - 1); return ret; } /// /// 優先度付きキューに含まれる最も価値が低い要素を削除せずに返します. /// /// 優先度付きキューに含まれる最も価値が低い要素. /// この操作は O(1) で実行されます. public T Peek() { return heap[0]; } /// /// 優先度付きキュー内の要素の数を取得します. /// /// 優先度付キュー内にある要素の数 /// 最悪計算量 O(1) で実行されます. public int Count { get { return heap.Count; } } /// /// 優先度付きキュー内に要素が存在するかどうかを O(1) で判定します. /// /// 優先度付キュー内にある要素が存在するならば true,そうでなければ false. /// この操作は O(1) で実行されます. public bool Any() { return heap.Count > 0; } /// /// 優先度付きキューに含まれる要素を昇順に並べて返します. /// /// この操作は計算量 O(N log N)で実行されます. public T[] Items { get { var ret = heap.ToArray(); Array.Sort(ret, cmp); return ret; } } } #endregion } /// /// SEGTREEは1-BASE運用でございます /// よろしくおねがいします /// /// class Segtree { int n;//高さ T[] tree;//本体 Func f;//更新関数。a -> b -> ab使ったなにか T exnum;//初期値 int count; public Segtree(int m, Func f, T ex) { this.count = 0; this.f = f; this.exnum = ex; n = 1; while (n < m) n <<= 1; tree = new T[(n << 1) - 1]; for (int i = 0; i < tree.Length; i++) tree[i] = ex; } public Segtree(int m, T ini, Func f, T ex) : this(m, f, ex) { this.count = 0; for (int i = 0; i < m; ++i) tree[i + n - 1] = ini; all_update(); } public void assign_without_update(int j, T x) { tree[j + n - 1] = x; } public void update(int j, T x)//j番目をxにする { int i = j + n - 1; tree[i] = x; while (i > 0) { i = (i - 1) >> 1; tree[i] = f(tree[(i << 1) + 1], tree[(i << 1) + 2]); } this.count++; } public void all_update() { for (int i = n - 2; i >= 0; i--) tree[i] = f(tree[(i << 1) + 1], tree[(i << 1) + 2]); } public T look(int i) { return tree[i + n - 1]; } public void delete(int j) { int i = j + n - 1; tree[i] = exnum; int moved = 0; while (true) { tree[i + 1] = tree[i]; T check = tree[i]; moved++; if (moved + j + 2 > count) { break; } } all_update(); } // [s, t) public T run(int s, int t) { return query(s, t, 0, 0, n); } T query(int s, int t, int k, int l, int r) { if (r <= s || t <= l) return exnum; if (s <= l && r <= t) return tree[k]; return f(query(s, t, (k << 1) + 1, l, (l + r) >> 1), query(s, t, (k + 1) << 1, (l + r) >> 1, r)); } }