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 JAVA (judge verdict: Time Limit Exceeded)

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.NoSuchElementException;
 
//Unordered Pair
class UP<A, B> {
    A a;
    B b;
 
    UP(A a, B b) {
        this.a = a;
        this.b = b;
    }
 
    static <A, B> UP<A, B> make(A a, B b) {
        return new UP<A, B>(a, b);
    }
 
    public UP<A, B> clone() {
        return make(a, b);
    }
 
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof UP))
            return false;
        UP<?, ?> p = (UP<?, ?>) o;
        boolean aok = a == null ? p.a == null : a.equals(p.a);
        boolean bok = b == null ? p.b == null : b.equals(p.b);
        return aok && bok;
    }
 
    public String toString() {
        return "(" + a.toString() + ", " + b.toString() + ")";
    }
}
 
interface F1<A> {
    A f();
}
 
interface F2<A, B> {
    B f(A a);
}
 
interface F3<A, B, C> {
    C f(A a, B b);
}
 
interface F4<A, B, C, D> {
    D f(A a, B b, C c);
}
 
// util
class U {
    static <A> ArrayList<A> make(int n, F2<Integer, A> maker) {
        ArrayList<A> res = new ArrayList<A>();
        for (int i = 0; i < n; i++) {
            res.add(maker.f(i));
        }
        return res;
    }
 
    static <A> ArrayList<A> filter(ArrayList<A> as, F2<A, Boolean> pred) {
        ArrayList<A> res = new ArrayList<A>();
        for (A a : as) {
            if (pred.f(a))
                res.add(a);
        }
        return res;
    }
 
    static <A> ArrayList<A> map(ArrayList<A> as, F2<A, A> f) {
        return make(as.size(), (i) -> f.f(as.get(i)));
    }
 
    static <A, B> ArrayList<UP<A, B>> zip(ArrayList<A> as, ArrayList<B> bs) {
        return make(min(as.size(), bs.size()), (i) -> UP.make(as.get(i), bs.get(i)));
    }
 
    static <A extends Comparable<A>> A min(A a, A b) {
        return a.compareTo(b) < 0 ? a : b;
    }
 
    static <A extends Comparable<A>> A max(A a, A b) {
        return a.compareTo(b) > 0 ? a : b;
    }
 
    static <A extends Comparable<A>> A clamp(A a, A min, A max) {
        return a.compareTo(min) < 0 ? min : a.compareTo(max) > 0 ? max : a;
    }
}
 
//Segment Tree
class ST<A> {
	// 0: unused, 1: root
	private ArrayList<A> dat;
	private int h;
	private int n;
	private F3<A, A, A> merger;
	private A e;

	ST(int num, F3<A, A, A> merger, A e) {
		this.merger = merger;
		this.e = e;
		h = 0;
		while ((1 << h) < num)
			h++;
		n = 1 << h;
		int size = 2 * n;
		dat = U.make(size, i -> e);
	}

	void init(A[] as) {
		for (int i = 0; i < n; i++) {
			this.dat.set(n + i, i < as.length ? as[i] : e);
		}
		for (int i = n - 1; i > 0; i--) {
			dat.set(i, merge(dat.get(i << 1), dat.get(i << 1 | 1)));
		}
	}

	A get(int i) {
		return query(i, i + 1);
	}

	void set(int i, A a) {
		i += n;
		dat.set(i, a);
		while ((i >>= 1) > 0) {
			dat.set(i, merge(dat.get(i << 1), dat.get(i << 1 | 1)));
		}
	}

	A query(int from, int until) {
		int l = from + n;
		int r = until + n;
		A res = e;
		while (l < r) {
			if ((r & 1) != 0) {
				res = merge(res, dat.get(--r));
			}
			if ((l & 1) != 0) {
				res = merge(res, dat.get(l++));
			}
		}
		return res;
	}

	private A merge(A a, A b) {
		return a == e ? b : b == e ? a : merger.f(a, b);
	}
}
 
public class Main {
 
    private static void solve() {
        int n = nei();
        int q = nei();
        int[][] qs = nis2(q, 3);
        ST<Integer> st = new ST<Integer>(n, (a, b) -> U.min(a, b), Integer.MAX_VALUE);
        for (int i = 0; i < q; i++) {
            if (qs[i][0] == 0) {
                st.set(qs[i][1], qs[i][2]);
            } else {
                out(st.query(qs[i][1], qs[i][2] + 1));
            }
        }
    }
 
    // returns (x, y, d) s.t. ax + by = d
    static long[] exgcd(long a, long b) {
        int sa = a < 0 ? -1 : 1;
        int sb = b < 0 ? -1 : 1;
        a *= sa;
        b *= sb;
        long x = 1;
        long y = 0;
        long z = 0;
        long w = 1;
        while (b > 0) {
            long q = a / b;
            long t = z;
            z = x - q * z;
            x = t;
            t = w;
            w = y - q * w;
            y = t;
            t = b;
            b = a - q * b;
            a = t;
        }
        return new long[] { x * sa, y * sb, a };
    }
 
    static int[] lis(int[] s) {
        int n = s.length;
        int[] dp = new int[n];
        int[] ids = new int[n];
        int[] pids = new int[n];
        dp[0] = s[0];
        int len = 1;
        int lidx = 0;
        for (int i = 1; i < n; i++) {
            int idx = bs(s[i], dp, 0, len);
            dp[idx] = s[i];
            ids[idx] = i;
            if (idx == len) {
                lidx = i;
                len++;
            }
            if (idx > 0)
                pids[i] = ids[idx - 1];
        }
        int[] lis = new int[len];
        lis[len - 1] = s[lidx];
        for (int i = len - 1; i >= 0; i--) {
            lis[i] = s[lidx];
            lidx = pids[lidx];
        }
        return lis;
    }
 
    static int bs(int a, int[] as, int from, int num) {
        int min = from;
        int max = from + num - 1;
        while (min < max) {
            int mid = min + max >> 1;
            if (as[mid] < a)
                min = mid + 1;
            else if (as[mid] > a)
                max = mid;
            else
                return mid;
        }
        return as[min] < a ? min + 1 : min;
    }
 
    static int gcd(int x, int y) {
        x = (x ^ x >> 31) - (x >> 31);
        y = (y ^ y >> 31) - (y >> 31);
        if (x < y) {
            x ^= y;
            y ^= x;
            x ^= y;
        }
        int z = x % y;
        if (z == 0)
            return y;
        return gcd(y, z);
    }
 
    static long gcd(long x, long y) {
        x = (x ^ x >> 63) - (x >> 63);
        y = (y ^ y >> 63) - (y >> 63);
        if (x < y) {
            x ^= y;
            y ^= x;
            x ^= y;
        }
        long z = x % y;
        if (z == 0)
            return y;
        return gcd(y, z);
    }
 
    static long modinv(long a, long mod) {
        return modpow(a, mod - 2, mod);
    }
 
    static long modpow(long a, long b, long mod) {
        if (b == 0)
            return 1;
        if ((b & 1) == 0) {
            long sqrt = modpow(a, b >> 1, mod);
            return sqrt * sqrt % mod;
        }
        return a * modpow(a, b - 1, mod) % mod;
    }
 
    static long fact(long n) {
        if (n <= 1)
            return 1;
        long res = 2;
        for (long i = 3; i <= n; i++) {
            res *= i;
        }
        return res;
    }
 
    static long modfact(long n, long mod) {
        if (n <= 1)
            return 1 % mod;
        long res = 2;
        for (long i = 3; i <= n; i++) {
            res *= i;
            res %= mod;
        }
        return res % mod;
    }
 
    // returns facts([0]) and invfacts([1])
    static long[][] enumfacts(int n, long mod) {
        int num = n + 10;
        long[][] res = new long[2][num];
        long[] facts = res[0];
        long[] invfacts = res[1];
        for (int i = 0; i < num; i++) {
            if (i <= 1) {
                facts[i] = 1;
                invfacts[i] = 1;
            } else {
                facts[i] = facts[i - 1] * i % mod;
                invfacts[i] = modinv(facts[i], mod);
            }
        }
        return res;
    }
 
    static long modcomb(long n, long m, long mod) {
        if (m > n)
            return 0;
        if (m > n - m) {
            m = n - m;
        }
        long numer = 1;
        for (int i = 0; i < m; i++) {
            numer = numer * (n - i) % mod;
        }
        long denom = modfact(m, mod);
        return numer * modinv(denom, mod) % mod;
    }
 
    static long modcomb(int n, int m, long[] facts, long[] invfacts, long mod) {
        if (m > n)
            return 0;
        long numer = facts[n];
        long denom = invfacts[m] * invfacts[n - m] % mod;
        return numer * denom % mod;
    }
 
    // res[i][0]: prime factor, res[i][1]: exponent
    static int[][] factorize(int n) {
        int[][] pfs = new int[32][2];
        int num = 0;
        for (int i = 2; i * i <= n; i++) {
            int count = 0;
            while (n % i == 0) {
                n /= i;
                count++;
            }
            if (count > 0) {
                pfs[num][0] = i;
                pfs[num][1] = count;
                num++;
            }
        }
        if (n > 1) {
            pfs[num][0] = n;
            pfs[num][1] = 1;
            num++;
        }
        int[][] res = new int[num][2];
        for (int i = 0; i < num; i++) {
            res[i][0] = pfs[i][0];
            res[i][1] = pfs[i][1];
        }
        return res;
    }
 
    static long lcm(long x, long y) {
        x = (x ^ x >> 63) - (x >> 63);
        y = (y ^ y >> 63) - (y >> 63);
        return x / gcd(x, y) * y;
    }
 
    static int abs(int x) {
        return x < 0 ? -x : x;
    }
 
    static long abs(long x) {
        return x < 0 ? -x : x;
    }
 
    static int min(int a, int b) {
        return a < b ? a : b;
    }
 
    static long min(long a, long b) {
        return a < b ? a : b;
    }
 
    static int max(int a, int b) {
        return a > b ? a : b;
    }
 
    static long max(long a, long b) {
        return a > b ? a : b;
    }
 
    static int clamp(int a, int min, int max) {
        return a < min ? min : a > max ? max : a;
    }
 
    static long clamp(long a, long min, long max) {
        return a < min ? min : a > max ? max : a;
    }
 
    static double clamp(double a, double min, double max) {
        return a < min ? min : a > max ? max : a;
    }
 
    static void out(String val) {
        IO.out(val);
    }
 
    static void out(Object val) {
        IO.out(String.valueOf(val));
    }
 
    static void out(int val) {
        IO.out(String.valueOf(val));
    }
 
    static void out(long val) {
        IO.out(String.valueOf(val));
    }
 
    static void out(char val) {
        IO.out(String.valueOf(val));
    }
 
    static void out(double val) {
        IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
    }
 
    static void out(boolean val) {
        IO.out(val ? "true" : "false");
    }
 
    static void kil(String val) {
        IO.out(val);
        IO.flush();
        System.exit(0);
    }
 
    static void kil(Object val) {
        IO.out(String.valueOf(val));
        IO.flush();
        System.exit(0);
    }
 
    static void kil(int val) {
        IO.out(String.valueOf(val));
        IO.flush();
        System.exit(0);
    }
 
    static void kil(long val) {
        IO.out(String.valueOf(val));
        IO.flush();
        System.exit(0);
    }
 
    static void kil(char val) {
        IO.out(String.valueOf(val));
        IO.flush();
        System.exit(0);
    }
 
    static void kil(double val) {
        IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
        IO.flush();
        System.exit(0);
    }
 
    static void kil(boolean val) {
        IO.out(val ? "true" : "false");
        IO.flush();
        System.exit(0);
    }
 
    static String nes() {
        return IO.next();
    }
 
    static int nei() {
        return IO.nextInt();
    }
 
    static long nel() {
        return IO.nextLong();
    }
 
    static double ned() {
        return IO.nextDouble();
    }
 
    static char nec() {
        return IO.nextChar();
    }
 
    static String[] nss(int n) {
        String[] as = new String[n];
        for (int i = 0; i < n; i++) {
            as[i] = IO.next();
        }
        return as;
    }
 
    static int[] nis(int n) {
        int[] as = new int[n];
        for (int i = 0; i < n; i++) {
            as[i] = IO.nextInt();
        }
        return as;
    }
 
    static long[] nls(int n) {
        long[] as = new long[n];
        for (int i = 0; i < n; i++) {
            as[i] = IO.nextLong();
        }
        return as;
    }
 
    static double[] nds(int n) {
        double[] as = new double[n];
        for (int i = 0; i < n; i++) {
            as[i] = IO.nextDouble();
        }
        return as;
    }
 
    static char[] ncs(int n) {
        char[] as = new char[n];
        for (int i = 0; i < n; i++) {
            as[i] = IO.nextChar();
        }
        return as;
    }
 
    static String[][] nss2(int n, int m) {
        String[][] as = new String[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                as[i][j] = IO.next();
            }
        }
        return as;
    }
 
    static int[][] nis2(int n, int m) {
        int[][] as = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                as[i][j] = IO.nextInt();
            }
        }
        return as;
    }
 
    static long[][] nls2(int n, int m) {
        long[][] as = new long[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                as[i][j] = IO.nextLong();
            }
        }
        return as;
    }
 
    static double[][] nds2(int n, int m) {
        double[][] as = new double[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                as[i][j] = IO.nextDouble();
            }
        }
        return as;
    }
 
    static char[][] ncs2(int n, int m) {
        char[][] as = new char[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                as[i][j] = IO.nextChar();
            }
        }
        return as;
    }
 
    static int parseInt(String val) {
        return Integer.parseInt(val);
    }
 
    static int parseInt(char val) {
        return Integer.parseInt(String.valueOf(val));
    }
 
    static long parseLong(String val) {
        return Long.parseLong(val);
    }
 
    public static void main(String[] args) {
        try {
            solve();
            IO.flush();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }
}
 
final class IO {
    private static final InputStream in = System.in;
    private static final PrintWriter out = new PrintWriter(System.out, false);
    private static final byte[] buffer = new byte[1024];
    private static int ptr = 0;
    private static int len = 0;
 
    private static boolean hasNextByte() {
        if (ptr < len)
            return true;
        ptr = 0;
        try {
            len = in.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return len > 0;
    }
 
    private static int readByte() {
        if (hasNextByte())
            return buffer[ptr++];
        else
            return -1;
    }
 
    static boolean hasNext() {
        byte c;
        while (hasNextByte() && ((c = buffer[ptr]) < '!' || c > '~'))
            ptr++;
        return hasNextByte();
    }
 
    static String next() {
        if (!hasNext())
            throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while (b >= '!' && b <= '~') {
            sb.append((char) b);
            b = readByte();
        }
        return sb.toString();
    }
 
    static char nextChar() {
        if (!hasNext())
            throw new NoSuchElementException();
        return (char) readByte();
    }
 
    static long nextLong() {
        if (!hasNext())
            throw new NoSuchElementException();
        long n = 0;
        int sign = 1;
        int b = readByte();
        if (b == '-') {
            sign = -1;
            b = readByte();
        }
        if (b < '0' || '9' < b)
            throw new NumberFormatException();
        while (true) {
            if ('0' <= b && b <= '9')
                n = n * 10 + b - '0';
            else if (b == -1 || b < '!' || b > '~')
                return n * sign;
            else
                throw new NumberFormatException();
            b = readByte();
        }
    }
 
    static int nextInt() {
        if (!hasNext())
            throw new NoSuchElementException();
        int n = 0;
        int sign = 1;
        int b = readByte();
        if (b == '-') {
            sign = -1;
            b = readByte();
        }
        if (b < '0' || '9' < b)
            throw new NumberFormatException();
        while (true) {
            if ('0' <= b && b <= '9')
                n = n * 10 + b - '0';
            else if (b == -1 || b < '!' || b > '~')
                return n * sign;
            else
                throw new NumberFormatException();
            b = readByte();
        }
    }
 
    static double nextDouble() {
        return Double.parseDouble(next());
    }
 
    static void out(String val) {
        out.println(val);
    }
 
    static void flush() {
        out.flush();
    }
}