QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#723819#3035. GhostMarkadiusz#WA 959ms4200kbC++235.8kb2024-11-08 00:56:552024-11-08 00:56:57

Judging History

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

  • [2024-11-08 00:56:57]
  • 评测
  • 测评结果:WA
  • 用时:959ms
  • 内存:4200kb
  • [2024-11-08 00:56:55]
  • 提交

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())
#ifdef DEBUG
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<<"}";}
#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;
		};

		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 = 20;
			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(left);
					D val_right = eval(right);
					if (val_left < val_right) {
						bb = left;
					}
					else {
						ee = right;
					}
				}
				new_events.emplace_back((bb + ee) / 2);
			}
			swap(new_events, events);
		}


		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(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;
				assert(leq(eval(p), answer));
			}
#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: 0
Wrong Answer
time: 959ms
memory: 4200kb

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:

wrong answer Error is to high: expected 0.025000, but got 0.024779