Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- struct edge
- {
- int v, to, cap, scap;
- edge(int a, int b, int c)
- {
- v = a, to = b, cap = c, scap = c;
- }
- edge() {}
- };
- struct rect
- {
- int x1, y1, x2, y2;
- };
- struct tri
- {
- int y1, y2, x;
- };
- bool operator < (const tri &a, const tri &b)
- {
- return a.y1 < b.y1;
- };
- const int N = 1e6 + 7;
- const int INF = 1e9 + 7;
- vector <edge> e;
- vector <int> g[N];
- int us[N];
- int usbs = 1;
- int d[N];
- int q[N];
- int ded[N];
- int ptr[N];
- vector <rect> fget[N];
- int after_bfs = 1;
- int visb = 1;
- ll ans = 0;
- int qh, qt;
- int s, t;
- int l;
- bool bfs()
- {
- qh = qt = 0;
- us[s] = usbs;
- q[qt++] = s;
- d[s] = 0;
- while (qh < qt)
- {
- int v = q[qh++];
- for (auto c : g[v])
- {
- if (us[e[c].to] != usbs && e[c].cap > 0)
- {
- d[e[c].to] = d[v] + 1;
- us[e[c].to] = usbs;
- q[qt++] = e[c].to;
- }
- }
- }
- return (us[t] == usbs++);
- }
- int dfs(int v = s, int c = 1e9)
- {
- if (!c)
- {
- return 0;
- }
- if (v == t)
- {
- ans += c;
- return c;
- }
- if (ded[v] != after_bfs)
- {
- ded[v] = after_bfs;
- ptr[v] = 0;
- }
- for (; ptr[v] < (int) g[v].size(); ptr[v]++)
- {
- int ind = g[v][ptr[v]];
- if (e[ind].cap > 0 && d[e[ind].to] == d[v] + 1)
- {
- int x = dfs(e[ind].to, min(c, e[ind].cap));
- if (x)
- {
- e[ind].cap -= x;
- e[ind ^ 1].cap += x;
- return x;
- }
- }
- }
- return 0;
- }
- void add_edge(int u, int v, int cap)
- {
- g[u].push_back(e.size());
- e.push_back({u, v, cap});
- g[v].push_back(e.size());
- e.push_back({v, u, 0});
- }
- ll dinic(int a, int b)
- {
- s = a, t = b;
- while (bfs())
- {
- after_bfs++;
- while (dfs())
- {
- continue;
- }
- }
- return ans;
- }
- vector <int> inds;
- int lel(int v, int l, int r, int i)
- {
- if (r - l == 1)
- {
- return v;
- }
- else
- {
- int m = (l + r) / 2;
- if (i < m)
- {
- return lel(v * 2 + 1, l, m, i);
- }
- else
- {
- return lel(v * 2 + 2, m, r, i);
- }
- }
- }
- void get(int v, int l, int r, int tl, int tr)
- {
- if (tl >= r || tr <= l)
- {
- return;
- }
- if (tl >= l && tr <= r)
- {
- inds.push_back(v);
- }
- else
- {
- int tm = (tl + tr) / 2;
- get(v * 2 + 1, l, r, tl, tm);
- get(v * 2 + 2, l, r, tm, tr);
- }
- }
- void build(int v, int l, int r, int ax, int bx, int n)
- {
- if (r - l == 1)
- {
- add_edge(l, ax + v, 1);
- add_edge(bx + v, n + l, 1);
- }
- else
- {
- int m = (l + r) / 2;
- build(v * 2 + 1, l, m, ax, bx, n);
- build(v * 2 + 2, m, r, ax, bx, n);
- add_edge(ax + v * 2 + 1, ax + v, INF);
- add_edge(ax + v * 2 + 2, ax + v, INF);
- add_edge(bx + v, bx + v * 2 + 1, INF);
- add_edge(bx + v, bx + v * 2 + 2, INF);
- }
- }
- int main()
- {
- #ifdef ONPC
- freopen("a.in", "r", stdin);
- //freopen("a.out", "w", stdout);
- #else
- //freopen("a.in", "r", stdin);
- //freopen("a.out", "w", stdout);
- #endif
- vector <rect> fre;
- int n, q;
- scanf("%d", &n);
- scanf("%d", &q);
- for (int i = 0; i < q; i++)
- {
- int x1, y1, x2, y2;
- scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
- x1--, y1--, x2--, y2--;
- fget[x2].push_back({x1, y1, x2, y2});
- }
- set <tri> s;
- s.insert({0, n - 1, 0});
- for (int i = 0; i < n; i++)
- {
- for (auto c : fget[i])
- {
- auto it = s.lower_bound({c.y1, -1, -1});
- vector <tri> gt;
- if (it != s.begin())
- {
- it--;
- gt.push_back(*it);
- it++;
- }
- bool b = false;
- while (it != s.end() && (it->y2 <= c.y2 || !b))
- {
- gt.push_back(*it);
- it++;
- if (it != s.end())
- {
- if (it->y2 > c.y2)
- {
- gt.push_back(*it);
- b = true;
- }
- }
- }
- for (auto d : gt)
- {
- if (max(d.y1, c.y1) > min(d.y2, c.y2))
- {
- continue;
- }
- s.erase(d);
- if (c.y1 <= d.y1 && d.y2 <= c.y2)
- {
- int a = d.x, b = c.x1 - 1;
- if (a <= b)
- {
- fre.push_back({a, d.y1, b, d.y2});
- }
- }
- else
- {
- if (d.y1 <= c.y1 && c.y2 <= d.y2)
- {
- auto was = d;
- was.y2 = c.y1 - 1;
- if (was.y1 <= was.y2)
- {
- s.insert(was);
- }
- was = d;
- was.y1 = c.y2 + 1;
- if (was.y1 <= was.y2)
- {
- s.insert(was);
- }
- int a = d.x, b = c.x1 - 1;
- if (a <= b)
- {
- fre.push_back({a, c.y1, b, c.y2});
- }
- }
- else if (d.y2 > c.y2)
- {
- auto was = d;
- was.y1 = c.y2 + 1;
- s.insert(was);
- int a = d.x, b = c.x1 - 1;
- if (a <= b)
- {
- fre.push_back({a, d.y1, b, c.y2});
- }
- }
- else if (d.y1 < c.y1)
- {
- auto was = d;
- was.y2 = c.y1 - 1;
- s.insert(was);
- int a = d.x, b = c.x1 - 1;
- if (a <= b)
- {
- fre.push_back({a, c.y1, b, d.y2});
- }
- }
- }
- }
- if (c.x2 != n - 1)
- {
- s.insert({c.y1, c.y2, c.x2 + 1});
- }
- }
- }
- for (auto c : s)
- {
- fre.push_back({c.x, c.y1, n - 1, c.y2});
- }
- inds.clear();
- get(0, n - 1, n, 0, n);
- int cnt = inds[0] + 1;
- for (auto c : fre)
- {
- int x1 = c.x1, y1 = c.y1, x2 = c.x2, y2 = c.y2;
- inds.clear();
- get(0, x1, x2 + 1, 0, n);
- vector <int> a = inds;
- inds.clear();
- get(0, y1, y2 + 1, 0, n);
- vector <int> b = inds;
- for (auto c : a)
- {
- for (auto d : b)
- {
- add_edge(n + n + c, n + n + cnt + d, INF);
- }
- }
- }
- build(0, 0, n, n + n, n + n + cnt, n);
- int st = n + n + cnt + cnt, en = n + n + cnt + cnt + 1;
- for (int i = 0; i < n; i++)
- {
- add_edge(st, i, 1);
- add_edge(i + n, en, 1);
- }
- printf("%lld\n", dinic(st, en));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement