QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#198014 | #6959. Fences | PPP# | AC ✓ | 353ms | 22588kb | C++17 | 5.3kb | 2023-10-02 23:32:47 | 2023-10-02 23:32:47 |
Judging History
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;
}
Details
Tip: Click on the bar to expand more detailed information
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