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)

#include<stdio.h>
#include<stdlib.h>

int leftChild(int index){
  return 2*index;
}

int rightChild(int index){
  return 2*index+1;
}

int leftBound(int index, const int N){
  while ( index < N )
    index *= 2;
  return index-N;
}

int rightBound(int index, const int N){
  while ( index < N )
    index = 2*index+1;
  return index-N;
}

void update(int *list, const int N, const int i, const int x){
  int current = N+i, even;
  list[current] = x;
  while ( current != 1 ){
    current /= 2;
    list[current] = list[leftChild(current)] < list[rightChild(current)] ? list[leftChild(current)] : list[rightChild(current)];
  }
  return;
}

int findMin(int *list, const int N, const int index, const int x, const int y){
  int left = leftBound(index,N);
  int right = rightBound(index,N);
  if ( x == left && y == right )
    return list[index];
  // check if range is in left subtree
  else if ( rightBound(leftChild(index),N) >= y )
    return findMin(list,N,2*index,x,y);
  // check if range is in right subtree
  else if ( leftBound(rightChild(index),N) <= x )
    return findMin(list,N,2*index+1,x,y);
  else {
    int leftMin = findMin(list,N,leftChild(index),x,rightBound(leftChild(index),N));
    int rightMin = findMin(list,N,rightChild(index),leftBound(rightChild(index),N),y);
    if ( leftMin < rightMin )
      return leftMin;
    else
      return rightMin;
  }
}

void print(int *list, int N){
  int i;
  for ( i = 0; i < 2*N; i++ )
    printf("%d%c", list[i], i==(2*N-1) ? '\n' : ' ');
  return;
}
  
int main(){
  int n, q, i = 1, N, com, x, y;
  scanf(" %d %d", &n, &q);
  while ( i <= n )
    i *= 2;
  N = i;
  int *list = (int *) malloc(sizeof(int[2*N]));
  for ( i = 0; i < 2*N; i++ )
    list[i] = (1 << 30) - 1 + (1 << 30);
  for ( i = 0; i < q; i++ ){
    scanf(" %d %d %d", &com, &x, &y);
    switch( com ){
    case 0:
      update(list, N, x, y);
      break;
    case 1:
      printf("%d\n", findMin(list, N, 1, x, y));
      break;
    }
  }
  return 0;
}