QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#557096#6403. Master of PolygonpandapythonerWA 0ms3608kbC++236.6kb2024-09-11 02:59:322024-09-11 02:59:32

Judging History

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

  • [2024-09-11 02:59:32]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3608kb
  • [2024-09-11 02:59:32]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;


#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-7;

struct vec {
    ll x, y;

    vec() {}
    vec(ll x, ll y) : x(x), y(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 (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 (a.x > b.x) 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) {
        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];
            assert(c.x != d.x);
            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 b.x >= xl) {
                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;
            } else if (a.x >= xl and a.x <= xr) {
                pos = get_pos(a);
            } else {
                assert(b.x >= xl and b.x <= xr);
                pos = get_pos(b);
            }
            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);
}


signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> n >> q;
    poly.resize(n);
    rep(i, n) cin >> poly[i].x >> poly[i].y;
    tests.resize(q);
    rep(i, q) {
        cin >> tests[i].first.x >> tests[i].first.y >> tests[i].second.x >> tests[i].second.y;
        if (tests[i].first.x > tests[i].second.x) {
            swap(tests[i].first, tests[i].second);
        }
    }
    solve();
    rep(i, q) {
        if (result[i]) {
            cout << "YES" << "\n";
        } else {
            cout << "NO" << "\n";
        }
    }
    return 0;
}


/*
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
Wrong Answer
time: 0ms
memory: 3608kb

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:

NO
NO
NO
NO
NO
NO

result:

wrong answer expected YES, found NO [1st token]