QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#557113#6403. Master of PolygonpandapythonerTL 0ms0kbC++238.7kb2024-09-11 03:33:522024-09-11 03:33:52

Judging History

你现在查看的是最新测评结果

  • [2024-09-11 03:33:52]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:0kb
  • [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

*/

Details

Tip: Click on the bar to expand more detailed information

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
...

result: