QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#723838 | #3035. Ghost | Markadiusz# | AC ✓ | 5179ms | 12732kb | C++23 | 6.5kb | 2024-11-08 01:19:50 | 2024-11-08 01:19:57 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
#define FOR(i,l,r) for(int i=(l);i<=(r);++i)
#define REP(i,n) FOR(i,0,(n)-1)
#define ssize(x) int(x.size())
auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";}
auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";}
#ifdef DEBUG
#define debug(X...) cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X)
#else
#define debug(...) {}
#endif
using D = double;
struct Tree {
vector<D> tree;
int sz = 1;
Tree(int n) {
while (sz < n)
sz *= 2;
tree.resize(2 * sz);
}
void add(int pos, D val) {
pos += sz;
while (pos) {
tree[pos] = max(tree[pos], val);
pos /= 2;
}
}
D que(int w, int a, int b, int l, int r) {
if (a > r or b < l) {
return 0;
}
if (a >= l and b <= r){
return tree[w];
}
const int mid = (a + b) / 2;
return max(
que(w * 2, a, mid, l, r),
que(w * 2 + 1, mid + 1, b, l, r)
);
}
D query(int l, int r) {
return que(1, 0, sz - 1, l, r);
}
};
const D eps = 1e-9;
bool equal(D a, D b) { return abs(a - b) < eps; }
bool my_equal(D a, D b) { return abs(a - b) < eps; }
bool leq(D a, D b) { return equal(a, b) or a <= b; }
bool le(D a, D b) {
bool ret = not equal(a, b) and a < b;
//debug(a, b, ret);
return ret;
}
struct Line {
mutable D a, b, p;
D eval(D x) const { return D(a) * x + D(b); }
bool operator<(const Line & o) const { return a < o.a; }
bool operator<(D x) const { return p < x; }
};
struct LineContainerMax : multiset<Line, less<>> {
/*
const LL inf = LLONG_MAX;
LL div(LL a, LL b) { return a / b - ((a ^ b) < 0 && a % b); }
*/
const D inf = 1 / .0;
D div(D a, D b) { return a / b; }
bool intersect(iterator x, iterator y) {
if (y == end()) { x->p = inf; return false; }
if (equal(x->a, y->a)) x->p = x->b > y->b ? inf : -inf;
else x->p = div(y->b - x->b, x->a - y->a);
return x->p >= y->p;
}
void add(D a, D b) {
//debug("max", a, b);
auto z = insert({a, b, 0}), y = z++, x = y;
while (intersect(y, z)) z = erase(z);
if (x != begin() && intersect(--x, y))
intersect(x, erase(y));
while((y = x) != begin() && (--x)->p >= y->p)
intersect(x, erase(y));
}
D query(D x) {
assert(!empty());
return lower_bound(x)->eval(x);
}
};
struct LineContainerMin : multiset<Line, less<>> {
/*
const LL inf = LLONG_MAX;
LL div(LL a, LL b) { return a / b - ((a ^ b) < 0 && a % b); }
*/
const D inf = 1 / .0;
D div(D a, D b) { return a / b; }
bool intersect(iterator x, iterator y) {
if (y == end()) { x->p = inf; return false; }
if (equal(x->a, y->a)) x->p = x->b > y->b ? inf : -inf;
else x->p = div(y->b - x->b, x->a - y->a);
return x->p >= y->p;
}
void add(D a, D b) {
//debug("min", a, b);
a = -a;
b = -b;
auto z = insert({a, b, 0}), y = z++, x = y;
while (intersect(y, z)) z = erase(z);
if (x != begin() && intersect(--x, y))
intersect(x, erase(y));
while((y = x) != begin() && (--x)->p >= y->p)
intersect(x, erase(y));
}
D query(D x) {
assert(!empty());
return -lower_bound(x)->eval(x);
}
};
int main() {
cin.tie(0)->sync_with_stdio(0);
cout << setprecision(10) << fixed;
int t;
cin >> t;
REP(tt, t) {
int n;
cin >> n;
vector<LineContainerMin> Min(2);
vector<LineContainerMax> Max(2);
REP(i, n) {
vector<int> bot(2), top(2), speed(2);
cin >> bot[0] >> bot[1];
cin >> top[0] >> top[1];
cin >> speed[0] >> speed[1];
debug(i, bot, top, speed);
REP(j, 2) {
Min[j].add(speed[j], top[j]);
Max[j].add(speed[j], bot[j]);
}
}
auto eval = [&](D x) {
auto one = max<D>(0, Min[0].query(x) - Max[0].query(x));
auto two = max<D>(0, Min[1].query(x) - Max[1].query(x));
auto ret = one * two;
/*
debug(x, ret, one, two);
debug(Min[0].query(x), Max[0].query(x));
debug(Min[1].query(x), Max[1].query(x));
*/
return ret;
};
auto eval_trin = [&](D x) {
auto one = Min[0].query(x) - Max[0].query(x);
auto two = Min[1].query(x) - Max[1].query(x);
auto ret = abs(one * two);
if (le(min(one, two), 0)) {
ret = -ret;
}
/*
debug(x, ret, one, two);
debug(Min[0].query(x), Max[0].query(x));
debug(Min[1].query(x), Max[1].query(x));
*/
return ret;
};
vector<D> events;
int q;
cin >> q;
vector<D> left(q), right(q);
auto process = [&](auto& h) {
vector<Line> v(h.begin(), h.end());
REP(i, ssize(v) - 1) {
auto [a, b, _] = v[i];
auto [c, d, _2] = v[i + 1];
debug(i, a, b, c, d);
const D x = D(d - b) / D(a - c);
if (equal(a, c))
continue;
debug(x);
events.emplace_back(x);
}
};
REP(i, 2) {
process(Min[i]);
process(Max[i]);
}
sort(events.begin(), events.end(), le);
debug(events);
events.erase(unique(events.begin(), events.end(), my_equal), events.end());
debug(events);
{
const int ITERS = 100;
vector<D> new_events = events;
REP(i, ssize(events) - 1) {
D bb = events[i], ee = events[i + 1];
REP(j, ITERS) {
if (equal(bb, ee))
break;
D left = (2 * bb + ee) / 3;
D right = (bb + 2 * ee) / 3;
D val_left = eval_trin(left);
D val_right = eval_trin(right);
if (val_left < val_right) {
bb = left;
}
else {
ee = right;
}
}
const D mid = (bb + ee) / 2;
debug(i, events[i], events[i + 1], mid, eval_trin(mid));
new_events.emplace_back(mid);
}
swap(new_events, events);
debug("new");
}
REP(i, q) {
cin >> left[i] >> right[i];
events.emplace_back(left[i]);
events.emplace_back(right[i]);
}
debug(left, right, events);
sort(events.begin(), events.end(), le);
debug("sorted new", events);
events.erase(unique(events.begin(), events.end(), my_equal), events.end());
debug(events);
auto get_id = [&](D x) {
auto it = lower_bound(events.begin(), events.end(), x, le);
assert(it != events.end());
//assert(*it == x);
return int(it - events.begin());
};
Tree tree(ssize(events));
REP(i, ssize(events)) {
tree.add(i, eval(events[i]));
}
debug(events);
REP(i, q) {
const int l = get_id(left[i]);
const int r = get_id(right[i]);
auto answer = tree.query(l, r);
debug(i, l, r, answer);
#ifdef LOCAL
const int s = 1e3;
FOR(j, 0, s) {
D p = (j * left[i] + (s - j) * right[i]) / s;
if (not leq(eval(p), answer)) {
cout << n << ' ' << left[i] << ' ' << right[i] << endl;
cout << p << ' ' << eval(p) << endl;
cout << answer << endl;
cout << events << endl;
assert(false);
}
}
#else
cout << answer << '\n';
#endif
}
#ifdef LOCAL
cout << "OK\n";
#endif
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 969ms
memory: 4132kb
input:
4000 2 -5 -5 3 1 1 -5 -3 -4 -1 2 -2 1 169 4.5924 9.7635 4.9674 5.3219 8.2418 9.6649 6.5743 8.6108 5.3524 6.4199 2.1932 4.3636 1.7115 6.6926 0.5762 4.0628 5.0348 7.5678 6.2170 6.3381 7.1571 8.0276 1.7285 2.3730 0.3843 2.9644 0.0038 0.3971 3.8448 9.7040 4.0458 9.4878 1.6425 7.9132 8.9195 9.4455 4.2563...
output:
0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 3.0856000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 5.3884000000 9.9544000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0...
result:
ok OK!
Test #2:
score: 0
Accepted
time: 5179ms
memory: 12732kb
input:
49 20119 453553 453553 999314 999117 128392 128392 625880 625880 999937 999372 -124296 -124296 -34395 -34395 999431 999379 617841 617841 773531 773531 999210 999826 -458742 -458742 -351946 -351946 999501 999848 827822 827822 751364 751364 999088 999855 -391959 -391959 698502 698502 999908 999195 -26...
output:
28458932215.1265830994 26610127672.5550765991 28532937150.6518630981 28532937150.6518630981 28232156121.9352760315 28014514974.4783325195 26633365234.9573669434 28014514974.4783325195 28532937150.6518630981 27190169607.0056800842 26644935633.6762886047 28165463153.1787910461 27524892494.2400932312 2...
result:
ok OK!
Test #3:
score: 0
Accepted
time: 1604ms
memory: 12228kb
input:
11 2437 -319663 -890371 927261 655392 1 3 -257629 -963537 454576 973758 5 -6 -143353 -761004 767384 895313 1 -4 -474255 -62583 604311 925105 -5 -7 -129789 -629223 875141 641849 3 6 -54357 -600036 845387 199014 2 3 -946287 -251448 306995 217922 7 -3 -480329 -265842 271418 189372 5 -4 -352502 -775709 ...
output:
64584.3750000000 64584.3750000000 64584.3750000000 56289.6359642400 37538.9864726400 64584.3750000000 64584.3750000000 64584.3750000000 64584.3750000000 47531.4868845600 63419.8381286400 49064.9138966400 20520.1087994400 64584.3750000000 64584.3750000000 64584.3750000000 64584.3750000000 58595.28998...
result:
ok OK!