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 Kotlin (judge verdict: Accepted)

class Segtree<Monoid> constructor(n : Int ,ori : Monoid, m_fun : (Monoid,Monoid) -> Monoid){
    var dat : MutableList<Monoid>
    //評価関数
    var check : (Monoid,Monoid) -> Monoid = m_fun
    //単位元
    var origin = ori
    //領域
    var range : Int = 1

    //初期化処理、配列の長さを確定させて、モノイドで埋める
    init {
        range = 1
        while (range < n) range *= 2
        dat = MutableList(2*range,{origin})
    }

    fun update(place : Int,value : Monoid){
        var tmp = place + range - 1
        dat[tmp] = value
        while(tmp > 0){
            tmp = (tmp-1).shr(1)
            dat[tmp] = check(dat[2*tmp+1],dat[2*tmp+2])
        }
    }

    fun setValue(place : Int ,value : Monoid){
        dat[place + range - 1] = value
    }

    fun que(a : Int,b :Int,k :Int,l : Int,r : Int) : Monoid{
        if(r <= a || b <= l)return origin
        if(a <= l && r <= b)return dat[k]
        return check(que(a,b,2*k+1,l,(l+r)/2),que(a,b,2*k+2,(l+r)/2,r))
    }
    //fun quety(a : Int,b : Int) = que(a,Math.min(b,range),0,0,range)

    fun quety(a : Int,b : Int) : Monoid{
        var L = origin
        var R = origin
        var A = a + range - 1
        var B = b + range - 1
        while(A < B){
            if(A and 1 == 0)L = check(L,dat[A++])
            if(B and 1 == 0)R = check(R,dat[--B])
            A = A.shr(1)
            B = B.shr(1)
        }
        return check(L,R)
    }

    fun makeTree(){
        var TmpRange = range
        while(TmpRange > 1){
            for(i in 0 until TmpRange step 2){
                val tmp = i + TmpRange - 1
                dat[(tmp- 1).shr(1)] = check(dat[tmp],dat[tmp+1])
            }
            TmpRange = TmpRange.shr(1)
        }
    }
}

fun main(args : Array<String>){
    val (n,q) = readLine()!!.split(' ').map{ it.toInt() }
    val tree = Segtree(n,1L.shl(31)-1,{a : Long,b : Long -> Math.min(a,b)})
    for(i in 0 until n)tree.setValue(0,1L.shl(31)-1)
    tree.makeTree()
    for(i in 0 until q){
        val (a,b,c) = readLine()!!.split(' ').map{ it.toInt() }
        if(a == 0){
            tree.update(b,c.toLong())
        }
        else{
            println(tree.quety(b,c+1))
        }
    }
}