-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrectangle_union.hpp
98 lines (82 loc) · 3.3 KB
/
rectangle_union.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <atcoder/lazysegtree>
namespace structures {
struct S {
int val, cnt;
static S op(S x, S y) {
if (x.val != y.val)
return (x.val < y.val ? x : y);
else
return {x.val, x.cnt + y.cnt};
}
static S e() { return {INT_MAX, 0}; }
};
struct F {
int add;
static S mapping(F f, S x) { return {x.val + f.add, x.cnt}; }
static F composition(F f, F g) { return {g.add + f.add}; }
static F id() { return {0}; }
};
} // namespace structures
long long rectangle_union(vector<int> l, vector<int> r, vector<int> d, vector<int> u) {
using namespace structures;
const int n = l.size();
vector<int> xs(2 * n), ys(2 * n);
copy(l.begin(), l.end(), xs.begin());
copy(r.begin(), r.end(), xs.begin() + n);
copy(d.begin(), d.end(), ys.begin());
copy(u.begin(), u.end(), ys.begin() + n);
sort(xs.begin(), xs.end());
sort(ys.begin(), ys.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
const int m = xs.size(), w = ys.size();
vector<int> l1 = l, r1 = r, d1 = d, u1 = u;
for (auto& e : l1) e = lower_bound(xs.begin(), xs.end(), e) - xs.begin();
for (auto& e : r1) e = lower_bound(xs.begin(), xs.end(), e) - xs.begin();
for (auto& e : d1) e = lower_bound(ys.begin(), ys.end(), e) - ys.begin();
for (auto& e : u1) e = lower_bound(ys.begin(), ys.end(), e) - ys.begin();
vector<vector<pair<int, pair<int, int>>>> lr(w);
{
vector<int> siz(w);
for (int i = 0; i < n; ++i) siz[d1[i]]++, siz[u1[i]]++;
for (int i = 0; i < w; ++i) lr[i].reserve(siz[i]);
}
for (int i = 0; i < n; ++i) {
lr[d1[i]].emplace_back(1, make_pair(l1[i], r1[i]));
lr[u1[i]].emplace_back(-1, make_pair(l1[i], r1[i]));
}
lazy_segtree<S, S::op, S::e, F, F::mapping, F::composition, F::id> seg(m);
for (int i = 0; i < m - 1; ++i) seg.set(i, S{0, xs[i + 1] - xs[i]});
long long res = 0;
for (int i = 0; i < w - 1; ++i) {
for (auto [k, p] : lr[i]) seg.apply(p.first, p.second, F{k});
auto [val, cnt] = seg.all_prod();
long long tmp = (xs[m - 1] - xs[0]) - (val == 0 ? cnt : 0);
res += tmp * (ys[i + 1] - ys[i]);
}
return res;
}
long long rectangle_union_small(vector<int> l, vector<int> r, vector<int> d, vector<int> u) {
using namespace structures;
const int n = l.size();
const int m = *max_element(r.begin(), r.end()), w = *max_element(u.begin(), u.end()) + 1;
vector<vector<pair<int, pair<int, int>>>> lr(w);
{
vector<int> siz(w);
for (int i = 0; i < n; ++i) siz[d[i]]++, siz[u[i]]++;
for (int i = 0; i < w; ++i) lr[i].reserve(siz[i]);
}
for (int i = 0; i < n; ++i) {
lr[d[i]].emplace_back(1, make_pair(l[i], r[i]));
lr[u[i]].emplace_back(-1, make_pair(l[i], r[i]));
}
lazy_segtree<S, S::op, S::e, F, F::mapping, F::composition, F::id> seg(m);
for (int i = 0; i < m; ++i) seg.set(i, S{0, 1});
long long res = 0;
for (int i = 0; i < w - 1; ++i) {
for (auto [k, p] : lr[i]) seg.apply(p.first, p.second, F{k});
auto [val, cnt] = seg.all_prod();
res += m - (val == 0 ? cnt : 0);
}
return res;
}