QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#383264#5540. City HallFOY#WA 1ms3624kbC++232.7kb2024-04-09 08:38:302024-04-09 08:38:30

Judging History

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

  • [2024-04-09 08:38:30]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3624kb
  • [2024-04-09 08:38:30]
  • 提交

answer

#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <climits>
#include <cassert>
using namespace std;
using ll = long long;
const int mn = 1e5+5;
using pll = pair<ll, ll>;
using minpq = priority_queue<pll, vector<pll>, greater<pll>>;

struct Line {
	mutable ll k, m, p;
	bool operator<(const Line& o) const { return k < o.k; }
	bool operator<(ll x) const { return p < x; }
};

struct LineContainer : multiset<Line, less<>> {
	// (for doubles, use inf = 1/.0, div(a,b) = a/b)
	static const ll inf = LLONG_MAX;
	ll div(ll a, ll b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); }
	bool isect(iterator x, iterator y) {
		if (y == end()) return x->p = inf, 0;
		if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
		else x->p = div(y->m - x->m, x->k - y->k);
		return x->p >= y->p;
	}
	void add(ll k, ll m) {
		auto z = insert({k, m, 0}), y = z++, x = y;
		while (isect(y, z)) z = erase(z);
		if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
		while ((y = x) != begin() && (--x)->p >= y->p)
			isect(x, erase(y));
	}
	ll query(ll x) {
		assert(!empty());
		auto l = *lower_bound(x);
		return l.k * x + l.m;
	}
};

ll cost(vector<pll> x, vector<pll> y) {
	ll best = 1e18;
	LineContainer l;
	for (int i = 0; i < x.size(); i++) {
		auto [y1, x1] = x[i];
		l.add(-(-2*y1), -(y1*y1 + 2*x1));
	}
	for (int j = 0; j < y.size(); j++) {
		auto [y2, x2] = y[j];
		best = min(best, -l.query(y2) + 2*x2 + y2*y2);
	}
	return best;
}

ll h[mn];
vector<int> adj[mn];
ll from[mn], to[mn];
bool vis[mn];
int main() {
	ll n, m, s, t; cin >> n >> m >> s >> t;
	for (int i = 1; i <= n; i++) {
		cin >> h[i];
		from[i] = 1e18;
		to[i] = 1e18;
	}
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v;
		adj[v].push_back(u);
		adj[u].push_back(v);
	}
	minpq q;
	q.push({0, s});
	from[s] = 0;
	while (q.size()) {
		auto [d, v] = q.top();
		q.pop();
		if (vis[v]) continue;
		vis[v] = true;
		for (auto x : adj[v]) {
			if (vis[x]) continue;
			ll y = d + (h[x]-h[v])*(h[x]-h[v]);
			if (from[x] > y) {
				from[x] = y;
				q.push({y, x});
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		vis[i] = false;
	}
	q.push({0, t});
	to[t] = 0;
	while (q.size()) {
		auto [d, v] = q.top();
		q.pop();
		if (vis[v]) continue;
		vis[v] = true;
		for (auto x : adj[v]) {
			if (vis[x]) continue;
			ll y = d + (h[x]-h[v])*(h[x]-h[v]);
			if (to[x] > y) {
				to[x] = y;
				q.push({y, x});
			}
		}
	}

	ll ans = 1e18;
	for (int i = 1; i <= n; i++) {
		vector<pll> x, y;
		for (int j : adj[i]) {
			x.push_back({h[j], from[j]});
			y.push_back({h[j], to[j]});
		}
		ans = min(ans, cost(x, y));
	}
	cout << ans/2;
	if (ans%2) cout << ".5";
	cout << endl;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3624kb

input:

5 6 1 3
5 100 8 2 10
1 2
2 3
2 5
1 4
4 5
3 5

output:

4.5

result:

ok found '4.5000000', expected '4.5000000', error '0.0000000'

Test #2:

score: 0
Accepted
time: 1ms
memory: 3596kb

input:

5 5 1 5
1 2 10 10 4
1 2
2 3
2 4
3 5
4 5

output:

3

result:

ok found '3.0000000', expected '3.0000000', error '0.0000000'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3592kb

input:

5 4 1 4
8 8 8 8 100
1 2
2 3
3 4
4 5

output:

0

result:

ok found '0.0000000', expected '0.0000000', error '-0.0000000'

Test #4:

score: -100
Wrong Answer
time: 1ms
memory: 3620kb

input:

2 1 1 2
0 100000
1 2

output:

10000000000

result:

wrong answer 1st numbers differ - expected: '0.0000000', found: '10000000000.0000000', error = '10000000000.0000000'