trait Monoid[T] {
  def empty: T
  def append(a: T,B: T): T
}

sealed trait Segtree[M] {
  def value: M
  def size: Int
  def rangeQuery(a: Int, b: Int): M
  def updated(k: Int, x: M): Segtree[M]
}

case class Leaf[M : Monoid](value: M) extends Segtree[M] {
  override val size = 1
  override def rangeQuery(a: Int, b: Int): M =
    if (a <= 0 && 1 <= b) value else implicitly[Monoid[M]].empty
  override def updated(k: Int, x: M) = Leaf(x)
}

case class Node[M](lch: Segtree[M], rch: Segtree[M])(implicit m: Monoid[M]) extends Segtree[M] {
  override val value = m.append(lch.value, rch.value)
  override val size = lch.size + rch.size
  override def rangeQuery(a: Int, b: Int): M =
    if (a <= 0 && size <= b) value
    else if (b <= 0 || size <= a) m.empty
    else {
      val lSize = lch.size
      val left = lch.rangeQuery(a, b)
      val right = rch.rangeQuery(a - lSize, b - lSize)
      m.append(left, right)
    }
  override def updated(k: Int, x: M): Segtree[M] =
    if (k < lch.size) Node(lch.updated(k, x), rch)
    else Node(lch, rch.updated(k - lch.size, x))
}

object Segtree {
  def build[M](n: Int)(implicit m: Monoid[M]): Segtree[M] =
    if (n <= 1) Leaf(m.empty)
    else Node(build(n / 2), build(n - n / 2))
}

object Main extends App {
  implicit object IntMonoid extends Monoid[Int] {
    def empty = Int.MaxValue
    def append(a: Int, b: Int) = a min b
  }

  val sc = new java.util.Scanner(System.in)
  val n, q = sc.nextInt
  Iterator.continually {
    try (Some(sc.nextInt, sc.nextInt, sc.nextInt)) catch {
      case util.control.NonFatal(t) => None
    }
  } .toStream
    .takeWhile(_.isDefined)
    .foldLeft(Segtree.build[Int](n)) { (rmq, in) =>
      in match {
        case Some((0, x, y)) => rmq.updated(x, y)
        case Some((_, x, y)) => {
          println(rmq.rangeQuery(x, y + 1))
          rmq
        }
        case None => rmq
      }
    }
}

//Main.main(null)