QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#557113 | #6403. Master of Polygon | pandapythoner | TL | 0ms | 0kb | C++23 | 8.7kb | 2024-09-11 03:33:52 | 2024-09-11 03:33:52 |
answer
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define double ld
#define len(a) int((a).size())
#define all(a) begin(a), end(a)
#define rep(i, n) for (int i = 0; i < (n); i++)
mt19937 rnd(234234);
ld pi = atan2l(0, -1);
double eps = 1e-9;
struct vec {
ll x, y;
vec() {}
vec(ll x, ll y) : x(x), y(y) {}
bool operator==(const vec& other) const {
return x == other.x and y == other.y;
}
};
vec operator+(const vec& a, const vec& b) {
return vec{ a.x + b.x, a.y + b.y };
}
vec operator-(const vec& a, const vec& b) {
return vec{ a.x - b.x, a.y - b.y };
}
ll operator*(const vec& a, const vec& b) {
return a.x * b.x + a.y * b.y;
}
ll operator%(const vec& a, const vec& b) {
return a.x * b.y - a.y * b.x;
}
ll sign(ll x) {
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
}
bool intersects(const vec& a, const vec& b, const vec& c, const vec& d) {
if ((a - b) % (c - d) == 0) {
if ((c - a) % (d - a) != 0) return false;
if ((a - c) % (b - c) != 0) return false;
if (max(a.x, b.x) < min(c.x, d.x) or max(c.x, d.x) < min(a.x, b.x)) return false;
if (max(a.y, b.y) < min(c.y, d.y) or max(c.y, d.y) < min(a.y, b.y)) return false;
return true;
}
if (sign((b - a) % (c - a)) * sign((b - a) % (d - a)) > 0) return false;
if (sign((d - c) % (a - c)) * sign((d - c) % (b - c)) > 0) return false;
return true;
}
int n, q;
vector<vec> poly;
vector<pair<vec, vec>> tests;
vector<int> result;
void solve_slow() {
result.resize(q);
rep(i, q) {
auto& [a, b] = tests[i];
result[i] = false;
rep(j, n) {
auto& c = poly[j];
auto& d = poly[j == n - 1 ? 0 : j + 1];
if (intersects(a, b, c, d)) {
result[i] = true;
break;
}
}
}
}
double get(const vec& a, const vec& b, ll x) {
if (a.x == b.x) return a.y;
return a.y + (double(x - a.x)) / (b.x - a.x) * (b.y - a.y);
}
vector<int> sift_ind(vector<int> ind) {
vector<int> result;
}
vector<pair<vec, vec>> pull_lines(const vector<vector<vec>>& curves, ll xl, ll xr) {
vector<pair<vec, vec>> result;
for (auto& curve : curves) {
for (int i = 0; i + 1 < len(curve); i += 1) {
vec a = curve[i], b = curve[i + 1];
if (make_pair(a.x, a.y) > make_pair(b.x, b.y)) swap(a, b);
if (a.x <= xl and b.x >= xr) {
result.push_back(make_pair(a, b));
}
}
}
return result;
}
vector<vector<vec>> cut_curves(const vector<vector<vec>>& curves, ll xl, ll xr) {
vector<vector<vec>> result;
for (auto& curve : curves) {
for (int l = 0; l < len(curve); l += 1) {
if (curve[l].x < xl or curve[l].x > xr) continue;
int r = l;
while (r + 1 < len(curve) and (xl <= curve[r + 1].x and curve[r + 1].x <= xr)) {
r += 1;
}
int nl = max(0, l - 1);
int nr = min(r + 1, len(curve) - 1);
result.push_back(vector<vec>(curve.begin() + nl, curve.begin() + nr + 1));
l = r;
}
}
return result;
}
void solve_rec(vector<vector<vec>> curves, vector<int> ind, ll xl, ll xr) {
vector<int> new_ind;
for (auto i : ind) {
if (!result[i] and tests[i].second.x >= xl and tests[i].first.x <= xr) new_ind.push_back(i);
}
ind = new_ind;
new_ind.clear();
if (curves.empty() or ind.empty()) {
return;
}
auto lines = pull_lines(curves, xl, xr);
curves = cut_curves(curves, xl, xr);
sort(all(lines), [&](const pair<vec, vec>& a, const pair<vec, vec>& b) {
if (a.first == b.first) {
return (a.second - a.first) % (b.second - b.first) > 0;
}
return get(a.first, a.second, xl) + eps < get(b.first, b.second, xl);
});
auto get_pos = [&](const vec& a) {
int tl = -1;
int tr = len(lines);
while (tl + 1 < tr) {
int tm = (tl + tr) / 2;
auto& [c, d] = lines[tm];
if (c.x == d.x) {
if (c.y < a.y) {
tl = tm;
} else {
tr = tm;
}
} else {
if ((d - c) % (a - c) > 0) {
tl = tm;
} else {
tr = tm;
}
}
}
return tl;
};
if (!lines.empty()) {
for (auto i : ind) {
auto& [a, b] = tests[i];
int pos = -1;
if (a.x >= xl and a.x <= xr) {
pos = get_pos(a);
} else if (b.x >= xl and b.x <= xr) {
pos = get_pos(b);
} else {
assert(a.x < xl and b.x > xr);
int tl = -1;
int tr = len(lines);
while (tl + 1 < tr) {
int tm = (tl + tr) / 2;
auto& [c, d] = lines[tm];
if (get(c, d, xl) + eps < get(a, b, xl)) {
tl = tm;
} else {
tr = tm;
}
}
pos = tl;
}
if (pos >= 0) {
if (intersects(a, b, lines[pos].first, lines[pos].second)) {
result[i] = true;
}
}
if (pos + 1 < len(lines)) {
if (intersects(a, b, lines[pos + 1].first, lines[pos + 1].second)) {
result[i] = true;
}
}
if (!result[i]) {
new_ind.push_back(i);
}
}
ind = new_ind;
new_ind.clear();
}
if (xl == xr) {
return;
}
if (xl + 1 == xr) {
solve_rec(curves, ind, xl, xl);
solve_rec(curves, ind, xr, xr);
return;
}
ll xm = (xl + xr) / 2;
solve_rec(curves, ind, xl, xm);
solve_rec(curves, ind, xm, xr);
}
void solve() {
result.assign(q, false);
vector<vector<vec>> curves = { poly };
curves.front().push_back(poly.front());
vector<int> ind(q);
rep(i, q) ind[i] = i;
solve_rec(curves, ind, 0, 30000);
}
bool good_coord(ll x) {
return 0 <= x and x <= 30000;
}
void stress() {
int c = 0;
while (1) {
cout << ++c << "\n";
n = rnd() % 10 + 1;
q = 1;
poly.resize(n);
rep(i, n) {
if (i == 0 or i == n - 1) {
poly[i].x = 2;
} else {
poly[i].x = rnd() % 7 + 3;
}
poly[i].y = i;
}
tests.resize(q);
rep(i, q) {
tests[i].first.x = rnd() % 10;
tests[i].first.y = rnd() % 10;
tests[i].second.x = rnd() % 10;
tests[i].second.y = rnd() % 10;
if (make_pair(tests[i].first.x, tests[i].first.y) >
make_pair(tests[i].second.x, tests[i].second.y)) {
swap(tests[i].first, tests[i].second);
}
}
solve_slow();
auto right_rs = result;
solve();
auto my_rs = result;
if (right_rs != my_rs) {
cout << n << " " << q << "\n";
rep(i, n) {
cout << poly[i].x << " " << poly[i].y << "\n";
}
rep(i, q) {
cout << tests[i].first.x << " " << tests[i].first.y << " " << tests[i].second.x << " " << tests[i].second.y << "\n";
}
break;
}
}
}
signed main() {
stress();
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> q;
poly.resize(n);
rep(i, n) {
cin >> poly[i].x >> poly[i].y;
assert(good_coord(poly[i].x));
}
tests.resize(q);
rep(i, q) {
cin >> tests[i].first.x >> tests[i].first.y >> tests[i].second.x >> tests[i].second.y;
assert(good_coord(tests[i].first.x));
assert(good_coord(tests[i].second.x));
if (make_pair(tests[i].first.x, tests[i].first.y) >
make_pair(tests[i].second.x, tests[i].second.y)) {
swap(tests[i].first, tests[i].second);
}
}
solve();
rep(i, q) {
if (result[i]) {
cout << "YES" << "\n";
} else {
cout << "NO" << "\n";
}
}
return 0;
}
/*
2 1
2 4
1 0
4 4 0 2
4 6
1 1
4 1
4 4
1 4
0 2 2 0
0 1 1 1
0 0 5 5
2 2 4 2
2 2 3 2
5 1 0 2
*/
详细
Test #1:
score: 0
Time Limit Exceeded
input:
4 6 1 1 4 1 4 4 1 4 0 2 2 0 0 1 1 1 0 0 5 5 2 2 4 2 2 2 3 2 5 1 0 2
output:
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 ...