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.Collections.Generic;
using System.Collections;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var nq = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
        var n = nq[0];
        var q = nq[1];
        var tree = new SegmentTree<int>(Enumerable.Repeat(int.MaxValue, n).ToArray(), (x,y) => Math.Min(x, y), int.MaxValue);
        var results = new List<int>();
        for(int i = 0; i < q; i++)
        {
            var inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();

            if(inputs[0] == 0)
            {
                tree.Update(inputs[1], inputs[2]);
            }
            else if(inputs[0] == 1)
            {
                var result = tree.Execute(inputs[1], inputs[2]+1);
                //Console.WriteLine(result);
                results.Add(result);
            }
        }

        foreach (var item in results) Console.WriteLine(item);
    }
}


public class SegmentTree<T>
{
    public int N { get; private set; }
    private T[] _tree;
    private readonly Func<T, T, T> _updateMethod;
    private readonly T _initValue;

    /// <summary>
    /// セグメント木の初期化
    /// </summary>
    /// <param name="items">要素達</param>
    /// <param name="updateMethod">更新する方法</param>
    /// <param name="initValue">セグメント木のノードの初期値</param>
    public SegmentTree(IEnumerable<T> items, Func<T, T, T> updateMethod, T initValue) {
        T[] array = items.ToArray();
        _updateMethod = updateMethod;
        _initValue = initValue;

        // セグ木の最下段は２の冪乗にする
        N = 1;
        while (N < array.Length) N *= 2;

        _tree = Enumerable.Repeat(initValue, 2 * N - 1).ToArray();

        // 最下段に要素達を入れた後、下の段から更新していく
        for (int i = 0; i < array.Length; i++) _tree[N + i - 1] = array[i];
        for (int i = N - 2; i >= 0; i--) _tree[i] = _updateMethod(_tree[2 * i + 1], _tree[2 * i + 2]);
    }

    /// <summary>
    /// 更新する
    /// </summary>
    /// <param name="i">更新したい値のインデックス</param>
    /// <param name="x">更新する値</param>
    public void Update(int i, T x)
    {
        // 更新したい要素のセグ木上でのインデックスを取得
        i = N + i - 1;

        // 値を更新した後に、どんどん親を更新していく
        _tree[i] = x;
        while(i > 0)
        {
            i = (i - 1) / 2;
            _tree[i] = _updateMethod(_tree[2 * i + 1], _tree[2 * i + 2]);
        }

        /*Console.Write("Tree : ");
        foreach(var item in _tree)
        {
            Console.Write(" " + item.ToString());
        }
        Console.WriteLine();*/
    }

    /// <summary>
    /// 区間内の目的の値を取得する
    /// </summary>
    /// <param name="a">要求区間[a, b)</param>
    /// <param name="b">要求区間[a, b)</param>
    /// <returns></returns>
    public T Execute(int a, int b)
    {
        //if (_tree.Length == 1) return _updateMethod(_tree[0], _initValue);
        return Execute(a, b, 0, 0, N);
    }

    private T Execute(int a, int b, int k, int l, int r)
    {
        // 要求区間[a, b)に対して対象区間[l, r)を求める
        // 今いるノードのインデックスがk

        // 要求区間と対象区間が交わらない
        if (r <= a || b <= l) return _initValue;

        // 要求区間が対象区間を完全に被覆
        if (a <= l && r <= b) return _tree[k];

        // 要求区間が対象区間の一部を被覆しているので、子について探索を行う
        // 新しい対象区間は、現在の対象区間を半分に割ったもの
        var vl = Execute(a, b, 2 * k + 1, l, (l + r) / 2);
        var vr = Execute(a, b, 2 * k + 2, (l + r) / 2, r);
        return _updateMethod(vl, vr);
    }
}