Skip to content

Commit d31bc98

Browse files
committed
add some codes for geometry
1 parent 202860b commit d31bc98

File tree

6 files changed

+681
-5
lines changed

6 files changed

+681
-5
lines changed
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
#include <cmath>
2+
#include <map>
3+
#include <vector>
4+
#include <functional>
5+
#include <algorithm>
6+
#include <iostream>
7+
8+
using flt = long double;
9+
using ll = long long;
10+
11+
const flt error = 1.3, eps = 1e-10, pi = acos(-1.0);
12+
const int N = 100000 + 10;
13+
14+
int sgn(flt x) {return x < -eps ? -1 : x > eps;}
15+
int sgn(ll x) {return x < 0 ? -1 : x > 0;}
16+
flt fix(flt x) {return x < eps ? x + pi * 2 : x;}
17+
18+
struct point {
19+
ll x, y;
20+
point(ll x = 0, ll y = 0): x(x), y(y) {}
21+
point(const point &rhs): x(rhs.x), y(rhs.y) {}
22+
bool operator < (const point &rhs) const {
23+
return x < rhs.x || (x == rhs.x && y < rhs.y);
24+
}
25+
bool operator <= (const point &rhs) const {
26+
return x < rhs.x || (x == rhs.x && y <= rhs.y);
27+
}
28+
bool operator == (const point &rhs) const {
29+
return x == rhs.x && y == rhs.y;
30+
}
31+
point operator + (const point &rhs) const {
32+
return point(x + rhs.x, y + rhs.y);
33+
}
34+
point operator - (const point &rhs) const {
35+
return point(x - rhs.x, y - rhs.y);
36+
}
37+
ll det(const point &rhs) const {
38+
return x * rhs.y - y * rhs.x;
39+
}
40+
ll dot(const point &rhs) const {
41+
return x * rhs.x + y * rhs.y;
42+
}
43+
flt norm() const {
44+
return hypot(x, y);
45+
}
46+
};
47+
48+
struct node {
49+
int sz;
50+
point p, ls, rs;
51+
node *l, *r;
52+
53+
node() = default;
54+
node(const point &x): sz(1), p(x), ls(x), rs(x), l(0), r(0) {}
55+
node* update() {
56+
sz = 1, ls = rs = p;
57+
if (r) sz += r->sz, rs = r->rs;
58+
if (l) sz += l->sz, ls = l->ls;
59+
return this;
60+
}
61+
};
62+
63+
bool random(int a, int b) {
64+
return rand() % (a + b) < a;
65+
}
66+
67+
ll ccw(const point &a, const point &b, const point &c) {
68+
return (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
69+
}
70+
71+
template<class cmp_t>
72+
struct convex_hull {
73+
cmp_t cmp;
74+
node *root;
75+
std::vector<std::pair<point, node*>> roll;
76+
void init() {
77+
root = 0;
78+
roll.clear();
79+
}
80+
int get_size(node *o) {
81+
if (o) return o->sz;
82+
else return 0;
83+
}
84+
node *kth(node *o, int k) {
85+
int cnt = get_size(o->l);
86+
if (k == cnt + 1) return o;
87+
if (k <= cnt) return kth(o->l, k);
88+
else return kth(o->r, k - cnt - 1);
89+
}
90+
template<typename T>
91+
std::pair<node*, node*> split(node *o, const point &p, T compare) {
92+
node *l = 0, *r = 0;
93+
if (!o) return {l, r};
94+
if (compare(o->p, p)) {
95+
std::tie(o->r, r) = split(o->r, p, compare);
96+
l = o;
97+
} else {
98+
std::tie(l, o->l) = split(o->l, p, compare);
99+
r = o;
100+
}
101+
o->update();
102+
return {l, r};
103+
}
104+
node* merge(node *l, node *r) {
105+
if (!l || !r) return l ? l : r;
106+
if (random(l->sz, r->sz)) {
107+
l->r = merge(l->r, r);
108+
return l->update();
109+
} else {
110+
r->l = merge(l, r->l);
111+
return r->update();
112+
}
113+
}
114+
bool has(node *o, const point &p) {
115+
if (!o) return false;
116+
if (o->p == p) return true;
117+
if (o->p < p) return has(o->r, p);
118+
else return has(o->l, p);
119+
}
120+
node *find_left(node *o, const point &p) {
121+
if (o->l) {
122+
if (!cmp(ccw(o->l->rs, o->p, p), 0)) {
123+
return find_left(o->l, p);
124+
}
125+
}
126+
if (o->r) {
127+
if (cmp(ccw(o->p, o->r->ls, p), 0)) {
128+
return find_left(o->r, p);
129+
}
130+
}
131+
return o;
132+
}
133+
node *find_right(node *o, const point &p) {
134+
if (o->r) {
135+
if (!cmp(ccw(p, o->p, o->r->ls), 0)) {
136+
return find_right(o->r, p);
137+
}
138+
}
139+
if (o->l) {
140+
if (cmp(ccw(p, o->l->rs, o->p), 0)) {
141+
return find_right(o->l, p);
142+
}
143+
}
144+
return o;
145+
}
146+
void add_point(const point &p) {
147+
if (has(root, p)) return;
148+
if (!root) {
149+
roll.emplace_back(p, root);
150+
root = new node(p);
151+
return;
152+
}
153+
if (root->ls < p && p < root->rs) {
154+
node *left_hull, *right_hull;
155+
std::tie(left_hull, right_hull) = split(root, p, std::less<point>());
156+
const point &l = left_hull->rs, &r = right_hull->ls;
157+
if (cmp(0, ccw(l, r, p))) {
158+
node *sl = find_left(left_hull, p), *sr = find_right(right_hull, p);
159+
node *a, *b;
160+
std::tie(left_hull, a) = split(left_hull, sl->p, std::less_equal<point>());
161+
std::tie(b, right_hull) = split(right_hull, sr->p, std::less<point>());
162+
root = merge(left_hull, merge(new node(p), right_hull));
163+
roll.emplace_back(p, merge(a, b));
164+
return;
165+
}
166+
root = merge(left_hull, right_hull);
167+
return;
168+
}
169+
if (p < root->ls) {
170+
node *sr = find_right(root, p), *b;
171+
std::tie(b, root) = split(root, sr->p, std::less<point>());
172+
roll.emplace_back(p, b);
173+
root = merge(new node(p), root);
174+
} else {
175+
node *sl = find_left(root, p), *a;
176+
std::tie(root, a) = split(root, sl->p, std::less_equal<point>());
177+
roll.emplace_back(p, a);
178+
root = merge(root, new node(p));
179+
}
180+
}
181+
void roll_back(size_t check_point) {
182+
while (roll.size() > check_point) {
183+
const point &p = roll.back().first;
184+
node *tree = roll.back().second;
185+
node *a, *b;
186+
std::tie(root, a) = split(root, p, std::less<point>());
187+
std::tie(a, b) = split(a, p, std::less_equal<point>());
188+
root = merge(root, merge(tree, b));
189+
roll.pop_back();
190+
}
191+
}
192+
node *kth(int k) {
193+
return kth(root, k + 1);
194+
}
195+
int size() {
196+
return get_size(root);
197+
}
198+
};
199+
200+
convex_hull<std::greater<ll>> upp_hull;
201+
convex_hull<std::less<ll>> low_hull;
202+
203+
struct query_t {
204+
char type;
205+
point p;
206+
int a, b, c;
207+
} queries[N];
208+
209+
inline node* get_point(int i) {
210+
int n = low_hull.size() + upp_hull.size() - 2;
211+
i %= n;
212+
if (i < 0) i += n;
213+
if (i < low_hull.size()) return low_hull.kth(i);
214+
else return upp_hull.kth(n - i);
215+
}
216+
217+
inline flt get_angle(const point &a, const point &b) {
218+
return fix(pi / 2 + atan2(b.y - a.y, b.x - a.x));
219+
}
220+
221+
inline flt get_angle(int i) {
222+
const point &a = get_point(i)->p;
223+
const point &b = get_point(i + 1)->p;
224+
return get_angle(a, b);
225+
}
226+
227+
int get_index(int a, int b) {
228+
flt angle = fix(pi / 2 + atan2(b, a));
229+
int left = 0, right = low_hull.size() + upp_hull.size() - 3;
230+
if (angle <= get_angle(0) || angle >= get_angle(right)) return 0;
231+
while (left < right) {
232+
int mid = (left + right - 1) / 2;
233+
if (get_angle(mid) > angle) right = mid;
234+
else left = mid + 1;
235+
}
236+
return right;
237+
}
238+
239+
std::pair<flt, flt> find(int a, int b, int c, int st, int ed, int side) {
240+
int n = low_hull.size() + upp_hull.size() - 2;
241+
int left = 0, right = (ed - st + n) % n;
242+
while (left < right) {
243+
int mid = (left + right - 1) / 2;
244+
const point &p = get_point(st + mid)->p;
245+
if (sgn(a * p.x + b * p.y + c) * side <= 0) right = mid;
246+
else left = mid + 1;
247+
}
248+
const point &p = get_point(st + left)->p;
249+
const point &q = get_point(st + left - 1)->p;
250+
flt d = p.y - q.y, e = q.x - p.x, f = q.y * (p.x - q.x) - q.x * (p.y - q.y);
251+
return {(c * e - b * f) / (b * d - a * e), (a * f - c * d) / (b * d - a * e)};
252+
}
253+
254+
flt get_intersect(int a, int b, int c, int i, int j) {
255+
const point &pa = get_point(i)->p;
256+
const point &pb = get_point(j)->p;
257+
int sa = sgn(a * pa.x + b * pa.y + c);
258+
int sb = sgn(a * pb.x + b * pb.y + c);
259+
if (sa == 0) {
260+
const point &tp1 = get_point(i + 1)->p;
261+
if (a * tp1.x + b * tp1.y + c == 0) return (tp1 - pa).norm();
262+
const point &tp2 = get_point(i - 1)->p;
263+
if (a * tp2.x + b * tp2.y + c == 0) return (tp2 - pa).norm();
264+
}
265+
if (sb == 0) {
266+
const point &tp1 = get_point(j + 1)->p;
267+
if (a * tp1.x + b * tp1.y + c == 0) return (tp1 - pb).norm();
268+
const point &tp2 = get_point(j - 1)->p;
269+
if (a * tp2.x + b * tp2.y + c == 0) return (tp2 - pb).norm();
270+
}
271+
if (sa * sb >= 0) return 0;
272+
auto p = find(a, b, c, i, j, sa);
273+
auto q = find(a, b, c, j, i, sb);
274+
return hypot(p.first - q.first, p.second - q.second);
275+
}
276+
277+
void solve(int l, int r, const std::vector<int> &add, const std::vector<int> &erase_time) {
278+
int mid = (l + r) / 2;
279+
int upp_check = upp_hull.roll.size();
280+
int low_check = low_hull.roll.size();
281+
std::vector<int> rest;
282+
for (auto &&st: add) {
283+
int ed = erase_time[st];
284+
if (ed <= l || st >= r) continue;
285+
if (st <= l && ed >= r) {
286+
upp_hull.add_point(queries[st].p);
287+
low_hull.add_point(queries[st].p);
288+
} else rest.push_back(st);
289+
}
290+
if (l + 1 == r) {
291+
if (queries[l].type == '?') {
292+
if (low_hull.size() + upp_hull.size() <= 2) {
293+
printf("%.20f\n", 0.0);
294+
} else {
295+
int a = queries[l].a, b = queries[l].b, c = queries[l].c;
296+
int i, j;
297+
if (!a) i = get_index(1, 0), j = get_index(-1, 0);
298+
else if (!b) i = get_index(0, 1), j = get_index(0, -1);
299+
else i = get_index(b, -a), j = get_index(-b, a);
300+
printf("%.20f\n", (double)get_intersect(a, b, c, i, j));
301+
}
302+
}
303+
} else {
304+
solve(l, mid, rest, erase_time);
305+
solve(mid, r, rest, erase_time);
306+
}
307+
upp_hull.roll_back(upp_check);
308+
low_hull.roll_back(low_check);
309+
}
310+
311+
int main() {
312+
int n;
313+
scanf("%d", &n);
314+
std::vector<int> erase_time(n, n);
315+
std::vector<int> add;
316+
for (int i = 0; i < n; ++i) {
317+
scanf(" %c", &queries[i].type);
318+
if (queries[i].type == '?') {
319+
scanf("%d%d%d", &queries[i].a, &queries[i].b, &queries[i].c);
320+
} else {
321+
int x, y, p;
322+
if (queries[i].type == '+') {
323+
scanf("%d%d", &x, &y);
324+
add.push_back(i);
325+
queries[i].p = {x, y};
326+
} else {
327+
scanf("%d", &p);
328+
erase_time[p - 1] = i;
329+
}
330+
}
331+
}
332+
upp_hull.init();
333+
low_hull.init();
334+
solve(0, n, add, erase_time);
335+
return 0;
336+
}

0 commit comments

Comments
 (0)