Skip to content

Commit dbdd7a1

Browse files
committed
P3122
1 parent ed9c2e6 commit dbdd7a1

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

code/luogu/P3122.cpp

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#include <algorithm>
2+
#include <cmath>
3+
#include <iostream>
4+
#include <set>
5+
#include <type_traits>
6+
#include <vector>
7+
8+
template <typename T>
9+
struct Point {
10+
T x, y;
11+
auto operator<=>(const Point &) const = default;
12+
};
13+
template <typename T, typename U>
14+
Point<std::common_type_t<T, U>> operator+(Point<T> p1, Point<U> p2) {
15+
return {p1.x + p2.x, p1.y + p2.y};
16+
}
17+
template <typename T, typename U>
18+
Point<std::common_type_t<T, U>> operator-(Point<T> p1, Point<U> p2) {
19+
return {p1.x - p2.x, p1.y - p2.y};
20+
}
21+
template <typename T>
22+
struct Line {
23+
Point<T> a, b;
24+
auto operator<=>(const Line &) const = default;
25+
};
26+
template <typename T>
27+
T dot(auto p1, auto p2) {
28+
return (T)p1.x * p2.y - (T)p2.x * p1.y;
29+
}
30+
auto arg(auto p) { return std::atan2l(p.y, p.x); }
31+
32+
using fp = long double;
33+
using i64 = int64_t;
34+
struct Convex {
35+
std::set<std::pair<fp, Point<int>>> h{};
36+
std::set<std::pair<fp, Line<int>>> t{};
37+
Point<fp> m{};
38+
39+
using Iter = decltype(h)::iterator;
40+
using IterT = decltype(t)::iterator;
41+
Iter prev(Iter it) const {
42+
if (it == h.begin()) it = h.end();
43+
return --it;
44+
}
45+
IterT prev(IterT it) const {
46+
if (it == t.begin()) it = t.end();
47+
return --it;
48+
}
49+
Iter next(Iter it) const {
50+
if (++it == h.end()) it = h.begin();
51+
return it;
52+
}
53+
IterT next(IterT it) const {
54+
if (++it == t.end()) it = t.begin();
55+
return it;
56+
}
57+
58+
auto make_line(Iter it1, Iter it2) {
59+
const auto &p1 = it1->second;
60+
const auto &p2 = it2->second;
61+
return std::make_pair(arg(p2 - p1), Line<int>(p1, p2));
62+
}
63+
void add(Iter it) {
64+
t.erase(make_line(prev(it), next(it)));
65+
t.insert(make_line(prev(it), it));
66+
t.insert(make_line(it, next(it)));
67+
}
68+
void del(Iter it) {
69+
t.insert(make_line(prev(it), next(it)));
70+
t.erase(make_line(prev(it), it));
71+
t.erase(make_line(it, next(it)));
72+
}
73+
74+
void init() {
75+
m = {};
76+
for (const auto [_, p] : h) {
77+
m = m + p;
78+
}
79+
m.x /= h.size();
80+
m.y /= h.size();
81+
82+
decltype(h) new_h{};
83+
for (const auto [_, p] : h) {
84+
new_h.emplace(arg(p - m), p);
85+
}
86+
h = std::move(new_h);
87+
88+
t.clear();
89+
for (auto it = h.begin(); it != h.end(); ++it) {
90+
t.insert(make_line(it, next(it)));
91+
}
92+
}
93+
94+
void insert(Point<int> p) {
95+
if (h.size() <= 2) {
96+
h.emplace(0, p);
97+
if (h.size() == 3) init();
98+
return;
99+
}
100+
101+
const auto [it, ok] = h.emplace(arg(p - m), p);
102+
if (!ok) return;
103+
104+
if (dot<i64>(prev(it)->second - p, next(it)->second - p) >= 0) {
105+
h.erase(it);
106+
return;
107+
}
108+
109+
add(it);
110+
while (h.size() > 3 && dot<i64>(next(it)->second - p,
111+
next(next(it))->second - p) <= 0) {
112+
del(next(it));
113+
h.erase(next(it));
114+
}
115+
while (h.size() > 3 && dot<i64>(prev(it)->second - p,
116+
prev(prev(it))->second - p) >= 0) {
117+
del(prev(it));
118+
h.erase(prev(it));
119+
}
120+
}
121+
122+
bool check(int a, int b, i64 c) const {
123+
auto eval = [a, b, c](Point<int> p) {
124+
return (i64)a * p.x + (i64)b * p.y - c;
125+
};
126+
127+
std::vector<Point<int>> check_list{};
128+
if (h.size() <= 8) {
129+
for (const auto [_, p] : h) check_list.push_back(p);
130+
} else {
131+
for (const fp theta :
132+
{arg(Point<int>{b, -a}), arg(Point<int>{-b, a})}) {
133+
auto it = t.lower_bound({theta, {}});
134+
if (it == t.end()) it = t.begin();
135+
check_list.push_back(prev(it)->second.a);
136+
check_list.push_back(prev(it)->second.b);
137+
check_list.push_back(next(it)->second.a);
138+
check_list.push_back(next(it)->second.b);
139+
}
140+
}
141+
142+
std::vector<i64> res{};
143+
for (const auto &p : check_list) {
144+
res.push_back(eval(p));
145+
}
146+
return std::ranges::max(res) < 0 || std::ranges::min(res) > 0;
147+
}
148+
};
149+
150+
int main() {
151+
std::ios::sync_with_stdio(false);
152+
std::cin.tie(nullptr);
153+
154+
int n, q;
155+
std::cin >> n >> q;
156+
157+
Convex h{};
158+
for (int i = 0; i < n; ++i) {
159+
int x, y;
160+
std::cin >> x >> y;
161+
h.insert({x, y});
162+
}
163+
164+
while (q--) {
165+
int op;
166+
std::cin >> op;
167+
if (op == 1) {
168+
int x, y;
169+
std::cin >> x >> y;
170+
h.insert({x, y});
171+
} else {
172+
int a, b;
173+
i64 c;
174+
std::cin >> a >> b >> c;
175+
const bool ans = h.check(a, b, c);
176+
std::cout << (ans ? "YES" : "NO") << '\n';
177+
}
178+
}
179+
}

0 commit comments

Comments
 (0)