-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathrectangle_union.cpp
More file actions
156 lines (148 loc) · 3.21 KB
/
rectangle_union.cpp
File metadata and controls
156 lines (148 loc) · 3.21 KB
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template <class T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define int long long int
#define pb push_back
#define pi pair<int, int>
#define pii pair<int, pi>
#define fir first
#define sec second
#define MAXN 200007
vector<int> x_vals;
struct segtree
{
vector<int> seg, tag;
segtree()
{
seg.assign(8 * x_vals.size(), 0);
tag.assign(8 * x_vals.size(), 0);
}
void add(int ql, int qr, int x, int v, int l, int r)
{
if (qr <= l || r <= ql)
{
return;
}
if (ql <= l && r <= qr)
{
tag[v] += x;
if (tag[v] == 0)
{
if (l != r)
seg[v] = seg[v << 1] + seg[(v << 1) | 1];
else
seg[v] = 0;
}
else
{
seg[v] = x_vals[r] - x_vals[l];
}
}
else
{
int mid = (l + r) >> 1;
add(ql, qr, x, (v << 1), l, mid);
add(ql, qr, x, ((v << 1) | 1), mid, r);
if (tag[v] == 0 && l != r)
seg[v] = seg[v << 1] + seg[(v << 1) | 1];
}
}
int qry()
{
return seg[1];
}
void upd(int l, int r, int x)
{
add(l, r, x, 1, 0, x_vals.size());
}
};
struct rect
{
int x1, y1, x2, y2;
};
struct event
{
int time, l, r, type;
bool operator<(const event &b)
{
if (time != b.time)
return time < b.time;
return type > b.type;
}
};
const int inf = 1e9;
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin >> n;
vector<rect> v(n);
for (int i = 0; i < n; i++)
{
cin >> v[i].x1 >> v[i].y1 >> v[i].x2 >> v[i].y2;
x_vals.pb(v[i].x1);
x_vals.pb(v[i].x2);
}
// comprime o x
sort(x_vals.begin(), x_vals.end());
x_vals.erase(unique(x_vals.begin(), x_vals.end()), x_vals.end());
vector<event> ev;
for (int i = 0; i < n; i++)
{
v[i].x1 = lower_bound(x_vals.begin(), x_vals.end(), v[i].x1) - x_vals.begin();
v[i].x2 = lower_bound(x_vals.begin(), x_vals.end(), v[i].x2) - x_vals.begin();
ev.pb({v[i].y1, v[i].x1, v[i].x2, 0}); // adicao
ev.pb({v[i].y2, v[i].x1, v[i].x2, 1}); // remocao
}
segtree s;
sort(ev.begin(), ev.end());
int area = 0, l = -inf;
for (auto const &i : ev)
{
if (l == -inf)
{
l = i.time;
s.upd(i.l, i.r, 1);
}
else if (i.type == 1)
{
int curr = s.qry();
s.upd(i.l, i.r, -1);
if (s.qry() != curr)
{
int new_t = (s.qry() == 0) ? -inf : i.time;
int lo = l, hi = i.time - 1;
area += ((hi - lo + 1) * curr);
l = new_t;
}
}
else
{
int curr = s.qry();
s.upd(i.l, i.r, 1);
if (s.qry() != curr)
{
int lo = l, hi = i.time - 1;
area += ((hi - lo + 1) * curr);
l = i.time;
}
}
}
cout << area << endl;
return 0;
}
// area da uniao de retangulos
// comprime coordenada no x pra montar a segtree dos valores de x
// faz o line sweep pelo y
// testado em dois judges:
// https://cses.fi/problemset/task/1741/
// n <= 10^5
// -10^6 <= x, y <= 10^6
// https://judge.yosupo.jp/problem/area_of_union_of_rectangles
// n <= 5 * 10^5
// 0 <= x, y <= 10^9