QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#198014#6959. FencesPPP#AC ✓353ms22588kbC++175.3kb2023-10-02 23:32:472023-10-02 23:32:47

Judging History

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

  • [2023-10-02 23:32:47]
  • 评测
  • 测评结果:AC
  • 用时:353ms
  • 内存:22588kb
  • [2023-10-02 23:32:47]
  • 提交

answer

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
struct pt{
    ll x, y;
};
int n, k;
const int maxN = 2e5 + 10;
pt a[maxN];
bool isCcw(pt a, pt b, pt c) {
    return (b.x - a.x) * (c.y - a.y) > (b.y - a.y) * (c.x - a.x);
}
bool isCw(pt a, pt b, pt c) {
    return (b.x - a.x) * (c.y - a.y) < (b.y - a.y) * (c.x - a.x);
}
ll area(pt a, pt b, pt c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
vector<pt> convexHull(vector<pt> pts) {
    if (pts.size() < 3) {
        return pts;
    }
    sort(pts.begin(), pts.end(), [&](const pt &a, const pt &b) {
        return make_pair(a.x, a.y) < make_pair(b.x, b.y);
    });
    pt pUp = pts.front(), pDown = pts.back();
    vector<pt> up{pUp}, down{pUp};
    for (size_t i = 1; i < pts.size(); ++i) {
        if (i == pts.size() - 1 || isCw(pUp, pts[i], pDown)) {
            while (up.size() >= 2 &&
                   !isCw(up[up.size()-2], up.back(), pts[i])) {
                up.pop_back();
            }
            up.push_back(pts[i]);
        }
        if (i == pts.size() - 1 || isCcw(pUp, pts[i], pDown)) {
            while (down.size() >= 2 &&
                   !isCcw(down[down.size()-2], down.back(), pts[i])) {
                down.pop_back();
            }
            down.push_back(pts[i]);
        }
    }
    assert(down.size() >= 2);
    for (size_t i = down.size() - 2; i > 0; --i) {
        up.push_back(down[i]);
    }
    return up;
}
ld len(pt a, pt b) {
    return sqrtl((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int tp(pt A) {
    if (A.y > 0 || (A.y == 0 && A.x > 0)) return -1;
    return 1;
}
bool cmp(const pt& A, const pt& B) {
    if (tp(A) != tp(B)) return tp(A) < tp(B);
    if (A.x * B.y != A.y * B.x) return A.x * B.y > A.y * B.x;
    return (A.x * A.x + A.y * A.y < B.x * B.x + B.y * B.y);
}
void solve() {
    cin >> n >> k;
    vector<pt> T;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].x >> a[i].y;
    }
    pt ini = a[k];
    for (int i = 1; i <= n; i++) {
        a[i].x -= ini.x;
        a[i].y -= ini.y;
        T.emplace_back(a[i]);
    }
    ini.x = 0;
    ini.y = 0;
    auto ch = convexHull(T);
    reverse(ch.begin(), ch.end());
    assert(ch.size() >= 3);
    ld cur = 0;
    for (int z = 0; z < ch.size(); z++) {
        cur += len(ch[z], ch[(z + 1) % ch.size()]);
    }
    for (int z = 1; z + 1 < ch.size(); z++) {
        assert(area(ch[0], ch[z], ch[z + 1]) > 0);
    }
//    for (auto& it :ch) {
//        cout << it.x << " " << it.y << endl;
//    }
    for (int z = 0; z < ch.size(); z++) {
        if (area(ch[z], ch[(z + 1) % ch.size()], ini) == 0) {
            cout << fixed << setprecision(3) << cur << '\n';
            return;
        }
    }
    vector<pt> S;
    for (int i = 1; i <= n; i++) {
        if (i == k) continue;
        S.emplace_back(a[i]);
    }
    sort(S.begin(), S.end(), cmp);
    vector<pt> nS;
    for (int z = 0; z < S.size(); z++) {
        if (z + 1 < S.size() && tp(S[z]) == tp(S[z + 1]) && S[z].x * S[z + 1].y == S[z].y * S[z + 1].x) {

        }
        else {
            nS.push_back(S[z]);
        }
    }
    S = nS;
    //S -- good
    ld best = 1e18;
    for (int t = 0; t < ch.size(); t++) {
        int l = lower_bound(S.begin(), S.end(), ch[t], cmp) - S.begin();
        int r = lower_bound(S.begin(), S.end(), ch[(t + 1) % ch.size()], cmp) - S.begin();
        assert(S[l].x == ch[t].x && S[l].y == ch[t].y);
        ld cand = cur - len(ch[t], ch[(t + 1) % ch.size()]);
        vector<pt> f;
        for (int z = l; z != r; z = (z + 1) % S.size()) {
            f.emplace_back(S[z]);
        }
        f.emplace_back(S[r]);
        vector<ld> down(f.size()), up(f.size());
        ld cur_s = 0;
        vector<pt> st;
        down[0] = len(ini, f[0]);
        st.push_back(f[0]);
        cur_s = 0;
        for (int i = 0; i + 2 < f.size(); i++) {
            while (st.size() >= 2 && area(f[i + 1], st[st.size() - 1], st[st.size() - 2]) >= 0) {
                cur_s -= len(st[st.size() - 1], st[st.size() - 2]);
                st.pop_back();
            }
            cur_s += len(st[st.size() - 1], f[i + 1]);
            down[i + 1] = cur_s + len(f[i + 1], ini);
            st.push_back(f[i + 1]);
        }
        cur_s = 0;
        st.clear();
        up[f.size() - 1] = len(ini, f.back());
        st.push_back(f.back());
        cur_s = 0;
        for (int i = f.size() - 2; i > 0; i--) {
            while (st.size() >= 2 && area(f[i], st[st.size() - 1], st[st.size() - 2]) <= 0) {
                cur_s -= len(st[st.size() - 1], st[st.size() - 2]);
                st.pop_back();
            }
            cur_s += len(st[st.size() - 1], f[i]);
            up[i] = cur_s + len(f[i], ini);
            st.push_back(f[i]);
        }
        for (int z = 0; z + 1 < f.size(); z++) {
            best = min(best, down[z] + up[z + 1] + cand);
        }
    }
    cout << fixed << setprecision(3) << best << '\n';
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef DEBUG
    freopen("input.txt", "r", stdin);
#endif
    int tst;
    cin >> tst;
    while (tst--) {
        solve();
    }
    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 353ms
memory: 22588kb

input:

10000
20 18
638759 -955696
82327 55245
268299 372341
-720833 -94921
340359 -625036
414233 369163
-505851 99899
177543 -104559
-163564 -716282
851182 -586314
693876 -357056
-571492 825083
59053 -650695
750440 -141379
-867846 -39074
-44757 716909
-734595 18431
-957928 843787
387329 328919
133912 39437...

output:

5695842.429
5877555.728
81.164
6548897.600
90.868
5353391.955
62.037
120.241
5133682.737
50.537
70.424
138.273
5023790.313
3961901.485
40.501
58.843
60.129
5346716.260
145.842
114.020
124.030
51.457
5236472.908
83.982
130.863
5433151.040
53.039
6564359.248
50.339
275.403
6165035.723
96.958
36.931
42...

result:

ok 10000 lines