There is a square grid of size $n \times n$. Some cells are colored in black, all others are colored in white. In one operation you can select some rectangle and color all its cells in white. It costs $\min(h, w)$ to color a rectangle of size $h \times w$. You are to make all cells white for minimum total cost.
The square is large, so we give it to you in a compressed way. The set of black cells is the union of $m$ rectangles.
Input
The first line contains two integers $n$ and $m$ ($1 \le n \le 10^{9}$, $0 \le m \le 50$) — the size of the square grid and the number of black rectangles.
Each of the next $m$ lines contains 4 integers $x_{i1}$ $y_{i1}$ $x_{i2}$ $y_{i2}$ ($1 \le x_{i1} \le x_{i2} \le n$, $1 \le y_{i1} \le y_{i2} \le n$) — the coordinates of the bottom-left and the top-right corner cells of the $i$-th black rectangle.
The rectangles may intersect.
Output
Print a single integer — the minimum total cost of painting the whole square in white.
Examples
input
10 2 4 1 5 10 1 4 10 5
output
4
input
7 6 2 1 2 1 4 2 4 3 2 5 2 5 2 3 5 3 1 2 1 2 3 2 5 3
output
3
Note
The examples and some of optimal solutions are shown on the pictures below.
Solution:
#include <bits/stdc++.h> using namespace std; template <typename T> class flow_graph { public: static constexpr T eps = (T) 1e-9; struct edge { int from; int to; T c; T f; }; vector<vector<int>> g; vector<edge> edges; int n; int st; int fin; T flow; flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); g.resize(n); flow = 0; } void clear_flow() { for (const edge &e : edges) { e.f = 0; } flow = 0; } int add(int from, int to, T forward_cap, T backward_cap) { assert(0 <= from && from < n && 0 <= to && to < n); int id = (int) edges.size(); g[from].push_back(id); edges.push_back({from, to, forward_cap, 0}); g[to].push_back(id + 1); edges.push_back({to, from, backward_cap, 0}); return id; } }; template <typename T> class dinic { public: flow_graph<T> &g; vector<int> ptr; vector<int> d; vector<int> q; dinic(flow_graph<T> &_g) : g(_g) { ptr.resize(g.n); d.resize(g.n); q.resize(g.n); } bool expath() { fill(d.begin(), d.end(), -1); q[0] = g.fin; d[g.fin] = 0; int beg = 0, end = 1; while (beg < end) { int i = q[beg++]; for (int id : g.g[i]) { const auto &e = g.edges[id]; const auto &back = g.edges[id ^ 1]; if (back.c - back.f > g.eps && d[e.to] == -1) { d[e.to] = d[i] + 1; if (e.to == g.st) { return true; } q[end++] = e.to; } } } return false; } T dfs(int v, T w) { if (v == g.fin) { return w; } int &j = ptr[v]; while (j >= 0) { int id = g.g[v][j]; const auto &e = g.edges[id]; if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) { T t = dfs(e.to, min(e.c - e.f, w)); if (t > g.eps) { g.edges[id].f += t; g.edges[id ^ 1].f -= t; return t; } } j--; } return 0; } T max_flow() { while (expath()) { for (int i = 0; i < g.n; i++) { ptr[i] = (int) g.g[i].size() - 1; } T big_add = 0; while (true) { T add = dfs(g.st, numeric_limits<T>::max()); if (add <= g.eps) { break; } big_add += add; } if (big_add <= g.eps) { break; } g.flow += big_add; } return g.flow; } vector<bool> min_cut() { max_flow(); vector<bool> ret(g.n); for (int i = 0; i < g.n; i++) { ret[i] = (d[i] != -1); } return ret; } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; vector<int> xa(m), ya(m), xb(m), yb(m); vector<int> xs = {0, n}; vector<int> ys = {0, n}; for (int i = 0; i < m; i++) { cin >> xa[i] >> ya[i] >> xb[i] >> yb[i]; --xa[i]; --ya[i]; xs.push_back(xa[i]); ys.push_back(ya[i]); xs.push_back(xb[i]); ys.push_back(yb[i]); } sort(xs.begin(), xs.end()); xs.resize(unique(xs.begin(), xs.end()) - xs.begin()); sort(ys.begin(), ys.end()); ys.resize(unique(ys.begin(), ys.end()) - ys.begin()); int nx = (int) xs.size() - 1; int ny = (int) ys.size() - 1; const long long inf = (long long) 2e18; flow_graph<long long> g(nx + ny + 2, nx + ny, nx + ny + 1); for (int i = 0; i < nx; i++) { g.add(nx + ny, i, xs[i + 1] - xs[i], 0); } for (int i = 0; i < ny; i++) { g.add(nx + i, nx + ny + 1, ys[i + 1] - ys[i], 0); } for (int i = 0; i < nx; i++) { for (int j = 0; j < ny; j++) { int ok = 0; for (int k = 0; k < m; k++) { if (xa[k] <= xs[i] && xs[i + 1] <= xb[k] && ya[k] <= ys[j] && ys[j + 1] <= yb[k]) { ok = 1; break; } } if (ok) { g.add(i, nx + j, inf, 0); } } } dinic<long long> d(g); cout << d.max_flow() << '\n'; return 0; }