QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#275755 | #7906. Almost Convex | Monohydroxides | WA | 15ms | 3648kb | C++20 | 5.0kb | 2023-12-05 00:19:49 | 2023-12-05 00:19:51 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using db = long double;
db eps = 1e-6;
db pi = acos(-1);
int sign(db a) {
return a < -eps ? -1 : a > eps;
}
int cmp(db a, db b) {
return sign(a - b);
}
struct Points {
db x, y;
Points(db _x = 0., db _y = 0.) : x(_x), y(_y) {}
int operator<(const Points &rhs) const {
int c = cmp(x, rhs.x);
if (c) {
return c == -1;
}
return cmp(y, rhs.y) == -1;
}
};
Points operator+(Points a, Points b) {
return Points(a.x + b.x, a.y + b.y);
}
Points operator-(Points a, Points b) {
return Points(a.x - b.x, a.y - b.y);
}
db dot(Points a, Points b) {
return a.x * b.x + a.y * b.y;
}
db Cross(Points a, Points b) {
return a.x * b.y - a.y * b.x;
}
db len(Points a) {
return sqrt(dot(a, a));
}
Points rotate(Points p, db angle) {
return Points(p.x * cos(angle) - p.y * sin(angle), p.x * sin(angle) + p.y * cos(angle));
}
db Angle(Points a, Points b) {
return acos(dot(a, b) / len(a) / len(b));
}
int quad(Points a) {
return sign(a.y) == 1 || (sign(a.y) == 0 && sign(a.x) >= 0);
}
db Cross(Points p1, Points p2, Points p3) {
return ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y));
}
int crossOp(Points p1, Points p2, Points p3) {
return sign(Cross(p1, p2, p3));
}
bool isMiddle(db a, db m, db b) {
return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
bool isMiddle(Points a, Points m, Points b) {
return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
bool OnSeg(Points p1, Points p2, Points q) {
return crossOp(p1, p2, q) == 0 && isMiddle(p1, q, p2);
}
vector<Points> convex_hell(vector<Points> &pts) {
sort(pts.begin(), pts.end());
int n = pts.size(), m = 0;
vector<Points> ch;
for (int i = 0; i < n; i++) {
while (m > 1 && Cross(ch[m - 1] - ch[m - 2], pts[i] - ch[m - 2]) <= 0) {
ch.pop_back();
m--;
}
ch.push_back(pts[i]);
m++;
}
int k = m;
for (int i = n - 2; i >= 0; i--) {
while (m > k && Cross(ch[m - 1] - ch[m - 2], pts[i] - ch[m - 2]) <= 0) {
ch.pop_back();
m--;
}
ch.push_back(pts[i]);
m++;
}
if (n > 1) {
ch.pop_back();
m--;
}
return ch;
}
int pointsInPoly(vector<Points> &p, Points a) {
int n = p.size(), ret = 0;
for (int i = 0; i < n; i++) {
Points u = p[i], v = p[(i + 1) % n];
if (OnSeg(u, v, a)) {
assert(0);
return 1;
}
if (cmp(u.y, v.y) <= 0) {
swap(u, v);
}
if (cmp(a.y, u.y) > 0 || cmp(a.y, v.y) <= 0) {
continue;
}
ret ^= crossOp(a, u, v) > 0;
}
return ret * 2;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<Points> pts;
for (int i = 1; i <= n; i++) {
int x, y;
cin >> x >> y;
pts.push_back(Points(double(x), double(y)));
}
auto ch = convex_hell(pts);
vector<Points> notOnConvVec;
map<Points, bool> onConv;
for (int i = 0; i < ch.size(); i++) {
onConv[ch[i]] = 1;
}
for (int i = 0; i < pts.size(); i++) {
if (!onConv.count(pts[i])) {
notOnConvVec.push_back(pts[i]);
}
}
if (notOnConvVec.size() == 0) {
cout << 1 << "\n";
return 0;
}
int ans = 1;
auto process = [&](vector<Points>& pts, Points a, Points b) {
db angle = Angle(Points(1.0, 0.0), b - a);
for (int i = 0; i < pts.size(); i++) {
pts[i] = pts[i] - a;
pts[i] = rotate(pts[i], 2 * pi - angle);
}
sort(pts.begin(), pts.end(), [](Points a, Points b) {
int qa = quad(a), qb = quad(b);
if (qa != qb) {
return qa < qb;
} else {
return sign(Cross(a, b)) > 0;
}
});
for (int i = 0; i < pts.size(); i++) {
pts[i] = rotate(pts[i], angle);
pts[i] = pts[i] + a;
}
};
for (int i = 0; i < ch.size(); i++) {
process(notOnConvVec, ch[i], ch[(i + 1) % ch.size()]);
vector<Points> tmp;
tmp.push_back(ch[i]);
tmp.push_back(ch[(i + 1) % ch.size()]);
tmp.push_back(notOnConvVec[0]);
ans++;
for (int j = 1; j < notOnConvVec.size(); j++) {
auto las = tmp.back();
tmp.pop_back();
tmp.push_back(notOnConvVec[j]);
if (!(pointsInPoly(tmp, las) >= 1)) {
ans++;
tmp.pop_back();
tmp.push_back(notOnConvVec[j]);
} else {
tmp.pop_back();
tmp.push_back(las);
}
}
}
cout << ans << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3496kb
input:
7 1 4 4 0 2 3 3 1 3 5 0 0 2 4
output:
9
result:
ok 1 number(s): "9"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3456kb
input:
5 4 0 0 0 2 1 3 3 3 1
output:
5
result:
ok 1 number(s): "5"
Test #3:
score: 0
Accepted
time: 1ms
memory: 3456kb
input:
3 0 0 3 0 0 3
output:
1
result:
ok 1 number(s): "1"
Test #4:
score: 0
Accepted
time: 0ms
memory: 3512kb
input:
6 0 0 3 0 3 2 0 2 1 1 2 1
output:
7
result:
ok 1 number(s): "7"
Test #5:
score: 0
Accepted
time: 0ms
memory: 3448kb
input:
4 0 0 0 3 3 0 3 3
output:
1
result:
ok 1 number(s): "1"
Test #6:
score: -100
Wrong Answer
time: 15ms
memory: 3648kb
input:
2000 86166 617851 383354 -277127 844986 386868 -577988 453392 -341125 -386775 -543914 -210860 -429613 606701 -343534 893727 841399 339305 446761 -327040 -218558 -907983 787284 361823 950395 287044 -351577 -843823 -198755 138512 -306560 -483261 -487474 -857400 885637 -240518 -297576 603522 -748283 33...
output:
787
result:
wrong answer 1st numbers differ - expected: '718', found: '787'