Problem: Write a program which manipulates a sequence A = {a0, a1, . . . , an−1} with the following operations:

* update(s, t, x): change as, as+1, ..., at to x.
* find(s, t): report the minimum element in as, as+1, ..., at.



Note that the initial values of ai (i = 0, 1, . . . , n−1) are 231-1.

Constraints

* 1 ≤ n ≤ 100000
* 1 ≤ q ≤ 100000
* 0 ≤ s ≤ t < n
* 0 ≤ x < 231−1

Input


n q
query1
query2
:
queryq


In the first line, n (the number of elements in A) and q (the number of queries) are given. Then, ith query queryi is given in the following format:


0 s t x


or


1 s t


The first digit represents the type of the query. '0' denotes update(s, t, x) and '1' denotes find(s, t).

Output

For each find operation, print the minimum value.

Examples

Input

3 5
0 0 1 1
0 1 2 3
0 2 2 2
1 0 2
1 1 2


Output

1
2


Input

1 3
1 0 0
0 0 0 5
1 0 0


Output

2147483647
5

Solution (in CPP):

Solution:
#include <algorithm>
#include <cstdio>
#include <functional>
#include <vector>

using namespace std;

#define int long long
#define dotimes(i, n) for (int i = 0, i##max__ = (n); i < i##max__; i++)
#define whole(f, x, ...) ([&](decltype((x)) c) { return (f)(begin(c), end(c), ## __VA_ARGS__); })(x)

int rint() {
  int x;
  scanf("%lld", &x);
  return x;
}

void wint(int x) {
  printf("%lld\n", x);
}

template<typename T> int size(T const& c) { return static_cast<int>(c.size()); }
template <typename T> bool maxs(T& a, T const& b) { return a < b ? a = b, true : false; }
template <typename T> bool mins(T& a, T const& b) { return a > b ? a = b, true : false; }
inline int lg(int x) { return 63 - __builtin_clzll(static_cast<unsigned int>(x)); }

class segment_tree {
  vector<int> xs;
public:
  segment_tree(int n) : xs(1 << (lg(2 * n - 1) + 1), (((1LL << 31) - 1) << 1) | 1) {}
  void update(int i, int j, int x) {
    x <<= 1;
    function<void(int, int, int)> rec;
    rec =
      [&](int k, int a, int b) {
        if (i <= a && b <= j)
          xs[k] = x | 1;
        else {
          if (xs[k] & 1)
            xs[2*k] = xs[2*k+1] = xs[k];
          int c = a + (b - a) / 2;
          if (j <= c)
            rec(2*k, a, c);
          else if (c <= i)
            rec(2*k+1, c, b);
          else {
            rec(2*k, a, c);
            rec(2*k+1, c, b);
          }
          xs[k] = (~1LL) & min(xs[2*k], xs[2*k+1]);
        }
      };
    rec(1, 0, ::size(xs)/2);
  }
  int query(const int i, const int j) {
    function<int(int, int, int)> rec;
    rec =
      [&](int k, int a, int b) {
        if ((i <= a && b <= j) || (xs[k] & 1))
          return xs[k];
        int c = a + (b - a) / 2;
        return j <= c ? rec(2*k, a, c) : c <= i ? rec(2*k+1, c, b) : min(rec(2*k, a, c), rec(2*k+1, c, b));
      };
    return rec(1, 0, ::size(xs)/2) >> 1;
  }
};

signed main() {
  const int n = rint();
  const int q = rint();
  segment_tree st(n);
  dotimes(i, q)
    if (rint()) {
      int s = rint();
      int t = rint();
      wint(st.query(s, t+1));
    } else {
      int s = rint();
      int t = rint();
      int x = rint();
      st.update(s, t+1, x);
    }
  return 0;
}