Problem:
Range Minimum Query (RMQ)

Write a program which manipulates a sequence A = {a0, a1, . . . , an-1} with the following operations:

find(s, t): report the minimum element in as, as+1, . . . ,at.

update(i, x): change ai to x.

Note that the initial values of ai (i = 0, 1, . . . , n−1) are 231-1.

Input

n q
com0 x0 y0
com1 x1 y1
...
comq−1 xq−1 yq−1

In the first line, n (the number of elements in A) and q (the number of queries) are given. Then, q queries are given where com represents the type of queries. '0' denotes update(xi, yi) and '1' denotes find(xi, yi).

Output

For each find operation, print the minimum element.

Constraints

1 ≤ n ≤ 100000

1 ≤ q ≤ 100000

If comi is 0, then 0 ≤ xi < n, 0 ≤ yi < 231-1.

If comi is 1, then 0 ≤ xi < n, 0 ≤ yi < n.

Sample Input 1

3 5
0 0 1
0 1 2
0 2 3
1 0 2
1 1 2

Sample Output 1

1
2

Sample Input 2

1 3
1 0 0
0 0 5
1 0 0

Sample Output 2

2147483647
5

Solution in C# (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;
using static System.Math;
namespace AtCoder
{
    class Program
    {
        static public int[] Sarray() { return ReadLine().Split().Select(int.Parse).ToArray(); }
        static public List<int> Slist() { return ReadLine().Split().Select(int.Parse).ToList(); }

        static readonly long Mod = 1000000000 + 7;
        static void Main(string[] args)
        {
            var NQ = Sarray();
            var N = NQ[0];
            var Q = NQ[1];
            var st = new SegmentTree<long>(N, Min, (2L << 30) - 1);

            for (var i = 0; i <Q ; ++i)
            {
                var ln = Sarray();
                if (0 == ln[0])
                    st.update(ln[1], ln[2]);
                else
                    WriteLine(st.query(ln[1], ln[2] + 1));
            }
        }
        class SegmentTree<Monoid>
        {
            int sz;
            Monoid[] seg;
            readonly Func<Monoid, Monoid, Monoid> f;
            readonly Monoid M1;

            public SegmentTree(int n, Func<Monoid,Monoid,Monoid    > f, Monoid M1)
            {
                this.f = f;
                this.M1 = M1;
                sz = 1;
                while (sz < n) sz <<= 1;
                seg = new Monoid[sz * 2].Select(_ => M1).ToArray();
            }
            public void set(int k, Monoid x) => seg[k + sz] = x;
            public void build()
            {
                for (var k = sz - 1; 0 < k; --k)
                    seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
            }
            public void update(int k, Monoid x)
            {
                k += sz;
                seg[k] = x;
                while (0 != (k >>= 1))
                    seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
            }
            //区間[a,b)に対して
            public Monoid query(int a,int b)
            {
                Monoid L = M1, R = M1;
                for (a += sz, b += sz; a < b; a >>= 1,b>>=1)
                {
                    if (0 != (a & 1)) L = f(L, seg[a++]);
                    if (0 != (b & 1)) R = f(seg[--b], R);
                }
                return f(L, R);
            }
            Monoid this[int k] => seg[k + sz];

        }
    }
}