QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#186114 | #4886. Best Sun | nhuang685 | WA | 306ms | 3800kb | C++20 | 17.6kb | 2023-09-23 08:12:50 | 2023-09-23 08:12:51 |
Judging History
answer
/**
* @file cf104491i-1.cpp
* @author n685
* @brief
* @date 2023-09-21
*
*
*/
#include <bits/stdc++.h>
#ifdef LOCAL
std::ifstream cin;
std::ofstream cout;
using std::cerr;
#else
using std::cin;
using std::cout;
#define cerr \
if (false) \
std::cerr
#endif
#ifdef LOCAL
#include "dd/debug.h"
#define dbg(...) lineInfo(__LINE__, #__VA_ARGS__), dbg1(__VA_ARGS__)
#define dbgR(...) lineInfo(__LINE__, #__VA_ARGS__), dbg2(__VA_ARGS__)
#define dbgP(p, ...) \
lineInfo(__LINE__, #__VA_ARGS__ " proj"), dbg3(p, __VA_ARGS__)
#define dbgRP(p, ...) \
lineInfo(__LINE__, #__VA_ARGS__ " proj"), dbg4(p, __VA_ARGS__)
void nline() { cerr << '\n'; }
#else
#define dbg(...) 42
#define dbgR(...) 4242
#define dbgP(...) 420
#define dbgRP(...) 420420
void nline() {}
#endif
using db = long double; // change it to double as needed
const db PI = std::acos(static_cast<db>(-1.0));
constexpr db EPS = 1e-7;
template <class T, class U> constexpr bool eq(const T &a, const U &b) {
if constexpr (std::is_floating_point<
typename std::common_type<T, U>::type>::value) {
return (std::abs((a - b) / std::max((db)1, (db)b)) < EPS);
} else {
return (a == b);
}
}
#define SIMPLE
template <class T> int sign(T v) { return (v > 0) - (v < 0); }
namespace G {
// based on https://codeforces.com/blog/entry/48122
template <class T> struct Point {
T x, y;
Point() : x(0), y(0) {}
Point(T _x, T _y) : x(_x), y(_y) {}
// arithmetic
template <class U> Point &operator+=(const Point<U> &b) {
x += static_cast<T>(b.x), y += static_cast<T>(b.y);
return (*this);
}
template <class U> Point &operator-=(const Point<U> &b) {
x -= static_cast<T>(b.x), y -= static_cast<T>(b.y);
return (*this);
}
template <class U> Point &operator*=(const U &b) {
x *= static_cast<T>(b), y *= static_cast<T>(b);
return (*this);
}
template <class U> Point &operator/=(const U &b) {
x /= static_cast<T>(b), y /= static_cast<T>(b);
return (*this);
}
// other
template <class U> operator Point<U>() const {
return Point<U>(static_cast<U>(x), static_cast<U>(y));
}
friend std::istream &operator>>(std::istream &in, Point &p) {
in >> p.x >> p.y;
return in;
}
friend std::ostream &operator<<(std::ostream &out, const Point &p) {
#ifdef SIMPLE
out << p.x << ' ' << p.y;
#else
out << '(' << p.x << ", " << p.y << ')';
#endif
return out;
}
};
template <class T1, class T2> auto makePoint(const T1 &x, const T2 &y) {
using R = typename std::common_type<T1, T2>::type;
return Point<R>(static_cast<R>(x), static_cast<R>(y));
}
// basic operations
template <class T1, class T2> auto operator*(const Point<T1> &a, const T2 &b) {
return makePoint(a.x * b, a.y * b);
}
template <class T1, class T2> auto operator*(const T1 &b, const Point<T2> &a) {
return makePoint(a.x * b, a.y * b);
}
template <class T1, class T2> auto operator/(const Point<T1> &a, const T2 &b) {
return makePoint(a.x / b, a.y / b);
}
template <class T> auto operator-(const Point<T> &a) {
// return makePoint(-a.x, -a.y);
return Point<T>(-a.x, -a.y);
}
template <class T1, class T2>
auto operator+(const Point<T1> &a, const Point<T2> &b) {
return makePoint(a.x + b.x, a.y + b.y);
}
template <class T1, class T2>
auto operator-(const Point<T1> &a, const Point<T2> &b) {
return makePoint(a.x - b.x, a.y - b.y);
}
template <class T1, class T2>
auto operator*(const Point<T1> &a, const Point<T2> &b) {
return a.x * b.x + a.y * b.y;
}
template <class T1, class T2>
auto operator^(const Point<T1> &a, const Point<T2> &b) {
return a.x * b.y - a.y * b.x;
}
// comparison - y takes priority
template <class T1, class T2>
bool operator==(const Point<T1> &a, const Point<T2> &b) {
return (eq(a.x, b.x) && eq(a.y, b.y));
}
template <class T1, class T2>
bool operator!=(const Point<T1> &a, const Point<T2> &b) {
return !(a == b);
}
template <class T1, class T2>
bool operator<(const Point<T1> &a, const Point<T2> &b) {
return eq(a.y, b.y) ? (a.x < b.x) : (a.y < b.y);
}
template <class T1, class T2>
bool operator>(const Point<T1> &a, const Point<T2> &b) {
return eq(a.y, b.y) ? (a.x > b.x) : (a.y > b.y);
}
template <class T1, class T2>
bool operator<=(const Point<T1> &a, const Point<T2> &b) {
return eq(a.y, b.y) ? (a.x <= b.x) : (a.y <= b.y);
}
template <class T1, class T2>
bool operator>=(const Point<T1> &a, const Point<T2> &b) {
return eq(a.y, b.y) ? (a.x >= b.x) : (a.y >= b.y);
}
// comparison - x takes priority
/* template <class T1, class T2>
bool operator==(const Point<T1> &a, const Point<T2> &b) {
return (eq(a.x, b.x) && eq(a.y, b.y));
}
template <class T1, class T2>
bool operator!=(const Point<T1> &a, const Point<T2> &b) {
return !(a == b);
}
template <class T1, class T2>
bool operator<(const Point<T1> &a, const Point<T2> &b) {
return eq(a.x, b.x) ? (a.y < b.y) : (a.x < b.x);
}
template <class T1, class T2>
bool operator>(const Point<T1> &a, const Point<T2> &b) {
return eq(a.x, b.x) ? (a.y > b.y) : (a.x > b.x);
}
template <class T1, class T2>
bool operator<=(const Point<T1> &a, const Point<T2> &b) {
return eq(a.x, b.x) ? (a.y <= b.y) : (a.x <= b.x);
}
template <class T1, class T2>
bool operator>=(const Point<T1> &a, const Point<T2> &b) {
return eq(a.x, b.x) ? (a.y >= b.y) : (a.x >= b.x);
} */
// angles
/**
* @brief determines if a comes before b in the counter-clockwise ordering
*
* @param a lhs
* @param b rhs
* @return -1 if a comes before b, 0 if a == b, and 1 if a comes after b
*/
template <class T1, class T2> int ccw(const Point<T1> &a, const Point<T2> &b) {
return sign(b ^ a);
}
template <class T1, class T2, class T3>
int ccw(const Point<T1> &a, const Point<T2> &b, const Point<T3> &o) {
return ccw(a - o, b - o);
}
template <class T> struct AngleCompare {
const Point<T> o;
AngleCompare(const Point<T> &origin = Point<T>()) : o(origin) {}
bool operator()(const Point<T> &a, const Point<T> &b) {
int v = ccw(a, b, o);
if (v == 0) {
return dist2(a, o) < dist2(b, o);
} else {
return v < 0;
}
}
};
template <class T1> auto angle(const Point<T1> &a) {
db d = std::atan2(static_cast<db>(a.y), static_cast<db>(a.x));
if (d < 0) {
d += 2 * PI;
}
return d;
}
template <class T1, class T2>
auto angle(const Point<T1> &a, const Point<T2> &b) {
db d = std::atan2(static_cast<db>(a ^ b), static_cast<db>(a * b));
if (d < 0) {
d += 2 * PI;
}
}
template <class T1, class T2, class T3>
auto angle(const Point<T1> &a, const Point<T2> &b, const Point<T3> &o) {
return angle(a - o, b - o);
}
template <class T> auto rotate(const Point<T> &a, db sa, db ca) {
return makePoint(ca * a.x - sa * a.y, sa * a.x + ca * a.y);
}
template <class T> auto rotate(const Point<T> &a, db angle) {
return rotate(a, std::sin(angle), std::cos(angle));
}
template <class T1, class T2>
auto rotate(const Point<T1> &a, const Point<T2> &o, db angle) {
return rotate(a - o, angle) + o;
}
template <class T> auto perp(const Point<T> &a) { return makePoint(-a.y, a.x); }
template <class T1, class T2>
auto perp(const Point<T1> &a, const Point<T2> &o) {
return perp(a - o) + o;
}
// distances
template <class T> auto norm2(const Point<T> &a) { return a * a; }
template <class T> db norm(const Point<T> &a) {
return std::sqrt(static_cast<db>(norm2(a)));
}
template <class T> auto abs(const Point<T> &a) {
return std::sqrt(static_cast<db>(norm2(a)));
}
template <class T1, class T2>
auto dist2(const Point<T1> &a, const Point<T2> &b) {
return norm2(a - b);
}
template <class T1, class T2> db dist(const Point<T1> &a, const Point<T2> &b) {
return norm(a - b);
}
template <class T1, class T2>
Point<db> bisector(const Point<T1> &a, const Point<T2> &b) {
return a * norm(b) + b * norm(a);
// return a / norm(a) + b / norm(b);
}
template <class T1, class T2, class T3>
Point<db> bisector(const Point<T1> &a, const Point<T2> &b, const Point<T3> &o) {
return bisector(a - o, b - o) + o;
}
template <class T> struct Line {
Point<T> a, ab;
Line() : a(), ab() {}
template <class T1, class T2>
Line(const Point<T1> &_a, const Point<T2> &_b, bool two_points = true) {
a = _a;
if (two_points) {
ab = _b - _a;
} else {
ab = _b;
}
}
Point<T> b() const { return (a + ab); }
friend std::ostream &operator<<(std::ostream &out, Line l) {
#ifdef SIMPLE
out << l.a << ' ' << l.b();
#else
out << l.a << " -> " << l.b();
#endif
return out;
}
// commenting this line out because it allowed for operations on bool like xor
// operator bool() const { return (ab != Point<T>()); }
bool line() const { return (ab != Point<T>()); }
Line operator-() const { return Line(b(), a); }
};
// a -> b or a -> (a + b)
template <class T1, class T2>
auto makeLine(const Point<T1> &a, const Point<T2> &b, bool two_points = true) {
using R = typename std::common_type<T1, T2>::type;
return Line<R>(static_cast<Point<R>>(a), static_cast<Point<R>>(b),
two_points);
}
// (x1, y1) -> (x2, y2)
template <class T1, class T2, class T3, class T4>
auto makeLine(const T1 &x1, const T2 &y1, const T3 &x2, const T4 &y2) {
return makeLine(makePoint(x1, y1), makePoint(x2, y2));
}
// Ax + By + C = 0
template <class T1, class T2, class T3>
auto makeLine(const T1 &A, const T2 &B, const T3 &C) {
assert(A != 0 || B != 0);
if (B == 0) {
return makeLine(makePoint(-static_cast<db>(C) / A, 0), makePoint(B, -A),
false);
} else {
return makeLine(makePoint(0, -static_cast<db>(C) / B), makePoint(B, -A),
false);
}
}
template <class T> std::array<T, 3> standard(const Line<T> &l) {
/* if (l.ab.y < 0)
return {-l.ab.y, l.ab.x, -l.ab.x * l.a.y + l.ab.y * l.a.x};
else */
return {l.ab.y, -l.ab.x, l.ab.x * l.a.y - l.ab.y * l.a.x};
}
template <class T> auto len2(const Line<T> &l) { return norm2(l.ab); }
template <class T> auto len(const Line<T> &l) { return norm(l.ab); }
/**
* @brief specifies the type of line; can take the three forms line, ray, and
* seg
*
*/
enum LineType { line, ray, seg };
template <LineType t, class T1, class T2>
bool on(const Point<T1> &p, const Line<T2> &l) {
if (!l.line()) {
return (p == l.a);
} else if (t >= 1 && ((p - l.a) * l.ab) <= 0) {
return (p == l.a);
} else if (t == 2 && ((p - l.b()) * l.ab) >= 0) {
return (p == l.b());
} else {
return eq((p - l.a) ^ l.ab, 0);
}
}
template <LineType t, class T1, class T2>
auto dist(const Point<T1> &p, const Line<T2> &l) {
if (!l.line()) {
return dist(p, l.a);
} else if (t >= 1 && ((p - l.a) * l.ab) <= 0) {
return dist(p, l.a);
} else if (t == 2 && ((p - l.b()) * l.ab) >= 0) {
return dist(p, l.b());
} else {
return std::abs((p - l.a) ^ l.ab) / norm(l.ab);
}
}
template <LineType t = line, class T1, class T2>
Point<db> closest(const Point<T1> &p, const Line<T2> &l) {
if (!l.line()) {
return l.a;
} else if (t >= 1 && ((p - l.a) * l.ab) <= 0) {
return l.a;
} else if (t == 2 && ((p - l.b()) * l.ab) >= 0) {
return l.b();
} else {
return l.a + l.ab * static_cast<db>((p - l.a) * l.ab) / norm2(l.ab);
}
}
template <LineType t = line, class T1, class T2>
Point<db> reflect(const Point<T1> &p, const Line<T2> &l) {
auto proj = closest<t>(p, l);
return 2 * proj - p;
}
/**
* @brief Determines and computes the intersection of two lines
*
* @tparam T1 type of first line
* @tparam T2 type of second line
* @tparam t1 line type of first line
* @tparam t2 line type of second line
* @param l1 first line
* @param l2 second line
* @return Whether the two lines interesct, as well as the point of
* intersection if and only if the lines intersect and are not parallel
*/
template <LineType t1, LineType t2, class T1, class T2>
std::pair<bool, Point<db>> intersect(const Line<T1> &l1, const Line<T2> &l2) {
if (!l1.line()) {
return {on<t2>(l1.a, l2), l1.a};
} else if (!l2.line()) {
return {on<t1>(l2.a, l1), l2.a};
}
if (eq(l1.ab ^ l2.ab, 0)) {
if (!eq(l1.ab ^ (l2.a - l1.a), 0)) {
return {false, Point<db>()};
}
if (t1 == line || t2 == line) {
return {true, Point<db>()};
}
if (t1 == seg) {
if (on<t2>(l1.a, l2) || on<t2>(l1.b(), l2)) {
return {true, Point<db>()};
}
}
if (t2 == seg) {
if (on<t1>(l2.a, l1) || on<t1>(l2.b(), l1)) {
return {true, Point<db>()};
}
}
if (t1 == ray && t2 == ray) {
if ((l1.ab * l2.ab) > 0 || on<t2>(l1.a, l2) || on<t1>(l2.a, l1)) {
return {true, Point<db>()};
}
}
return {false, Point<db>()};
}
// ((l1.a + i * l1.ab - l2.a) ^ l2.ab) == 0
auto i = (l2.a - l1.a) ^ l2.ab;
auto j = (l1.a - l2.a) ^ l1.ab;
auto d = l1.ab ^ l2.ab;
if (d < 0 && ((t1 == 2 && i < d) || (t1 >= 1 && i > 0) ||
(t2 == 2 && j > -d) || (t2 >= 1 && j < 0))) {
return {false, Point<db>()};
} else if (d > 0 && ((t1 == 2 && i > d) || (t1 >= 1 && i < 0) ||
(t2 == 2 && j < -d) || (t2 >= 1 && j > 0))) {
return {false, Point<db>()};
} else {
return {true, l1.a + static_cast<db>(i) / d * l1.ab};
}
}
template <LineType t1, LineType t2, class T1, class T2>
db dist(const Line<T1> &l1, const Line<T2> &l2) {
if (!l1.line()) {
return dist<t2>(l1.a, l2);
} else if (!l2.line()) {
return dist<t1>(l2.a, l1);
}
if (intersect<t1, t2>(l1, l2).first) {
return 0;
}
return std::min({dist<t2>(l1.a, l2), dist<t2>(l1.b(), l2), dist<t1>(l2.a, l1),
dist<t1>(l2.b(), l1)});
}
} // namespace G
using namespace G;
struct Event {
int type;
int i, j;
};
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
constexpr db EPS2 = 1e-7;
db area(G::Point<int64_t> a, G::Point<int64_t> b, G::Point<int64_t> c) {
return std::abs((db)((a ^ b) + (b ^ c) + (c ^ a)) / 2);
}
void solve() {
int n;
cin >> n;
std::vector<G::Point<int64_t>> p(n);
for (int i = 0; i < n; ++i) {
cin >> p[i];
}
#ifndef LOCAL
std::shuffle(p.begin(), p.end(), rng);
#endif
std::vector<Event> v;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
v.push_back(Event{0, i, j});
v.push_back(Event{0, j, i});
v.push_back(Event{1, i, j});
v.push_back(Event{1, j, i});
}
}
std::ranges::sort(v, {}, [&](auto a) {
db d = G::angle(p[a.i] - p[a.j]) + ((a.type) ? PI / 2 : (db)0);
if (d >= 2 * PI) {
d -= 2 * PI;
}
return std::pair{d, -a.type};
});
std::vector<std::vector<db>> off(n, std::vector<db>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) {
continue;
}
G::Line<int64_t> l = G::makeLine(p[i], p[j]);
for (int k = 0; k < n; ++k) {
if (k == i || k == j) {
continue;
}
if (G::ccw(p[k] - p[i], p[j] - p[i]) < 0 &&
G::on<G::seg>(G::closest<G::line>(p[k], l), l)) {
off[j][i] += std::min(G::dist(p[k], p[i]), G::dist(p[k], p[j]));
}
}
}
}
cerr << std::fixed;
dbg(area(p[0], p[2], p[3]));
dbg(G::dist(p[0], p[2]) + G::dist(p[0], p[3]) + G::dist(p[2], p[3]));
dbg(G::dist(p[3], p[1]));
db ans = 0;
for (int s = 0; s < n; ++s) {
std::vector<std::vector<bool>> g(n, std::vector<bool>(n));
auto good = [&](db x) {
std::vector<db> dp(n, -4e18), sub(n);
dp[s] = 0;
for (auto [type, i, j] : v) {
if (type == 0) {
if (!g[i][j] && i != s && j != s) {
continue;
}
dp[i] = std::max(dp[i], dp[j] + area(p[s], p[i], p[j]) -
x * (G::dist(p[i], p[j]) + off[i][j]));
} else {
dp[j] -= x * G::dist(p[i], p[j]);
sub[j] += G::dist(p[i], p[j]);
}
}
return (dp[s] >= 0);
};
std::vector<int> lp;
for (int i = 0; i < n; ++i) {
if (s != i && p[s].y <= p[i].y) {
lp.push_back(i);
}
}
std::ranges::sort(lp, G::AngleCompare<int64_t>(p[s]),
[&](auto a) { return p[a]; });
int m = (int)lp.size();
for (int ii = 0; ii < m; ++ii) {
int i = lp[ii];
if (s == i || p[s].y > p[i].y) {
continue;
}
G::Point<int64_t> mi = p[i] - p[s] + p[i];
for (int jj = ii + 1; jj < m; ++jj) {
int j = lp[jj];
if (s == j || p[s].y > p[j].y) {
continue;
}
G::Point<int64_t> d = p[j];
if (G::ccw(mi, d, p[i]) < 0) {
g[i][j] = true;
g[j][i] = true;
mi = d;
}
}
}
if (good(ans)) {
db l = ans, r = 4e18;
while (std::abs(r - l) >= EPS2) {
db mid = (l + r) / 2;
if (good(mid)) {
l = mid;
} else {
r = mid;
}
}
ans = l;
}
}
cout << std::fixed << std::setprecision(10) << ans << '\n';
}
int main() {
#ifdef LOCAL
cin.open("input.txt");
cout.rdbuf()->pubsetbuf(0, 0);
cout.open("output.txt");
#else
cin.tie(nullptr)->sync_with_stdio(false);
#endif
int t;
cin >> t;
while (t--) {
solve();
}
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3720kb
input:
4 3 -1 -1 1 -1 0 1 4 0 0 10 0 0 10 8 1 5 2 0 -2 0 1 1 -1 1 0 3 8 4 4 -4 4 4 -4 -4 -4 5 6 -6 5 -5 -6 6 -5
output:
0.3090169442 1.2368614048 0.2711375005 1.5631001976
result:
ok 4 numbers
Test #2:
score: 0
Accepted
time: 286ms
memory: 3776kb
input:
10000 3 702262 828158 -350821 -420883 -466450 13507 3 28647 -193498 126436 -864937 -287798 738936 3 270358 -269567 745815 -485408 834083 677952 3 -2036 -403634 742978 -263774 975937 -609237 3 584248 -472620 482016 -356760 284902 903881 3 -292004 504925 -935756 373793 -781101 -434659 3 -858513 684433...
output:
85789.0873983158 18268.5193616575 102489.9883902175 66685.7544280601 18674.6579374049 106468.9651319694 14427.0246510532 29966.2453025225 143547.7510835873 13097.1756881016 162410.1683169449 72070.9324178377 29369.9926278403 52867.2944310582 90314.3083467309 99775.9271965303 144449.7053083594 64406....
result:
ok 10000 numbers
Test #3:
score: 0
Accepted
time: 283ms
memory: 3728kb
input:
10000 3 2 2 2 -2 -5 -5 3 -3 5 5 -4 2 -2 3 -4 1 2 -2 -4 4 3 1 -4 2 1 -4 1 3 2 1 -1 1 -3 3 3 4 5 3 -1 -3 -3 3 1 5 5 0 5 -1 3 2 -3 -5 -3 5 3 3 -4 4 0 -5 5 4 3 2 -3 5 0 2 -5 3 -2 -3 5 -3 5 4 3 -1 4 4 4 4 3 3 5 3 -1 4 2 -1 3 2 -3 4 3 -4 3 3 0 4 -2 -2 -1 -3 3 -2 0 -4 -2 4 2 3 -3 -1 3 1 1 -3 3 2 -5 2 3 -4 ...
output:
0.6507006983 0.2268090466 0.4946825440 0.8255326103 0.2675324406 0.7379284448 0.1368528964 0.8277457837 1.3896281188 0.2484761638 1.0251262256 0.2252451065 0.7981688035 1.0521776166 0.2700907551 0.2210279846 0.6549291422 1.0657925442 0.1207361611 0.1727212056 0.4458825068 0.2484761638 0.1224985728 0...
result:
ok 10000 numbers
Test #4:
score: -100
Wrong Answer
time: 306ms
memory: 3800kb
input:
5625 4 -405394 -381883 602267 -335687 -620806 984110 271283 531233 4 196903 -993060 290851 358123 -890076 -717709 -681138 209884 4 -849589 607722 -21517 -586295 208561 -220953 924518 622983 4 -832186 456270 289934 43656 636006 339718 188963 113907 4 -305762 -872205 -520125 368722 -774548 984204 4245...
output:
232625.0042744195 268175.8269859392 159589.3236305029 60440.7530425788 133893.1234363069 63201.9907485773 167697.6634061081 129470.0132843088 126903.8540727764 106643.9712630879 131692.3112278920 100421.0550161786 148490.2748178730 68842.2423098133 241376.1911161095 303904.5464356353 77462.333614771...
result:
wrong answer 1740th numbers differ - expected: '76473.2065795', found: '83504.3345687', error = '0.0919424'