QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#275715 | #7906. Almost Convex | Monohydroxides | WA | 1ms | 3516kb | C++20 | 6.8kb | 2023-12-04 23:41:48 | 2023-12-04 23:41:48 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using db = long double;
// db eps = 1e-14;
// 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 {
i64 x, y;
Points(i64 _x = 0., i64 _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;
// }
int operator<(const Points &rhs) const {
return x == rhs.x ? y < rhs.y : x < rhs.x;
}
};
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;
// }
i64 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;
// }
i64 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));
// }
i64 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));
// }
int crossOp(Points p1, Points p2, Points p3) {
i64 c = Cross(p1, p2, p3);
if (c < 0) {
return -1;
} else if (c == 0) {
return 0;
}
return 1;
}
// bool isMiddle(db a, db m, db b) {
// return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
// }
bool isMiddle(i64 a, i64 m, i64 b) {
return a == m || b == m || (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 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 (u.y <= v.y) {
swap(u, v);
}
if (a.y > u.y || a.y <= v.y) {
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;
// // }
// return cmp(Cross(a, b), 0.) > 0;
// });
// for (int i = 0; i < pts.size(); i++) {
// // pts[i] = rotate(pts[i], angle);
// pts[i] = pts[i] + a;
// }
// };
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;
// }
return 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()]);
ans++;
for (int j = 1; j < notOnConvVec.size(); j++) {
if (Cross(notOnConvVec[j], notOnConvVec[j - 1]) < 0) {
ans++;
}
}
}
cout << ans << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3500kb
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: -100
Wrong Answer
time: 1ms
memory: 3516kb
input:
5 4 0 0 0 2 1 3 3 3 1
output:
6
result:
wrong answer 1st numbers differ - expected: '5', found: '6'