QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#723838#3035. GhostMarkadiusz#AC ✓5179ms12732kbC++236.5kb2024-11-08 01:19:502024-11-08 01:19:57

Judging History

This is the latest submission verdict.

  • [2024-11-08 01:19:57]
  • Judged
  • Verdict: AC
  • Time: 5179ms
  • Memory: 12732kb
  • [2024-11-08 01:19:50]
  • Submitted

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!