QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#383236 | #5540. City Hall | kevinyang# | WA | 0ms | 3624kb | C++17 | 4.8kb | 2024-04-09 06:26:15 | 2024-04-09 06:26:15 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf = (int)2e18;
struct Line {
int m, c;
int eval(int x) {
return m * x + c;
}
};
struct node {
Line line;
node* left = nullptr;
node* right = nullptr;
node(Line line) : line(line) {}
void add_segment(Line nw, int l, int r, int L, int R) {
if (l > r || r < L || l > R) return;
int m = (l + 1 == r ? l : (l + r) / 2);
if (l >= L and r <= R) {
bool lef = nw.eval(l) < line.eval(l);
bool mid = nw.eval(m) < line.eval(m);
if (mid) swap(line, nw);
if (l == r) return;
if (lef != mid) {
if (left == nullptr) left = new node(nw);
else left -> add_segment(nw, l, m, L, R);
}
else {
if (right == nullptr) right = new node(nw);
else right -> add_segment(nw, m + 1, r, L, R);
}
return;
}
if (max(l, L) <= min(m, R)) {
if (left == nullptr) left = new node({0, inf});
left -> add_segment(nw, l, m, L, R);
}
if (max(m + 1, L) <= min(r, R)) {
if (right == nullptr) right = new node ({0, inf});
right -> add_segment(nw, m + 1, r, L, R);
}
}
int query_segment(int x, int l, int r, int L, int R) {
if (l > r || r < L || l > R) return inf;
int m = (l + 1 == r ? l : (l + r) / 2);
if (l >= L and r <= R) {
int ans = line.eval(x);
if (l < r) {
if (x <= m && left != nullptr) ans = min(ans, left -> query_segment(x, l, m, L, R));
if (x > m && right != nullptr) ans = min(ans, right -> query_segment(x, m + 1, r, L, R));
}
return ans;
}
int ans = inf;
if (max(l, L) <= min(m, R)) {
if (left == nullptr) left = new node({0, inf});
ans = min(ans, left -> query_segment(x, l, m, L, R));
}
if (max(m + 1, L) <= min(r, R)) {
if (right == nullptr) right = new node ({0, inf});
ans = min(ans, right -> query_segment(x, m + 1, r, L, R));
}
return ans;
}
};
struct LiChaoTree {// the input values for lichaotree are boundaries of x values you can use to query with
int L, R;
node* root;
LiChaoTree() : L(numeric_limits<int>::min() / 2), R(numeric_limits<int>::max() / 2), root(nullptr) {}
LiChaoTree(int L, int R) : L(L), R(R) {
root = new node({0, inf});
}
void add_line(Line line) {
root -> add_segment(line, L, R, L, R);
}
// y = mx + b: x in [l, r]
void add_segment(Line line, int l, int r) {
root -> add_segment(line, L, R, l, r);
}
int query(int x) {
return root -> query_segment(x, L, R, L, R);
}
int query_segment(int x, int l, int r) {
return root -> query_segment(x, l, r, L, R);
}
};
int n,m,s,t;
vector<int> dijkstra(vector<vector<pair<int,int>>>adj, int src){
vector<int>dis(n+1,(int)1e18);
vector<bool>vis(n+1);
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>pq;
pq.push({0,src});
dis[src] = 0;
while(pq.size()){
auto [dist,cur] = pq.top(); pq.pop();
if(vis[cur])continue;
vis[cur] = true;
for(auto [w,nxt] : adj[cur]){
if(dis[nxt] > w + dist){
dis[nxt] = w + dist;
pq.push({dis[nxt],nxt});
}
}
}
return dis;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> m >> s >> t;
vector<vector<pair<int,int>>>adj(n+1);
vector<int>h(n+1);
for(int i = 1; i<=n; i++){
cin >> h[i];
}
for(int i = 0; i<m; i++){
int x,y;
cin >> x >> y;
int w = (h[x]-h[y])*(h[x]-h[y]);
adj[x].push_back({w,y});
adj[y].push_back({w,x});
}
vector<int>dis = dijkstra(adj, s);
vector<int>dis2 = dijkstra(adj, t);
for(int i = 1; i<=n; i++){
dis[i]*=2;
dis2[i]*=2;
}
int ans = (int)1e18;
for(auto [w,nxt] : adj[s]){
if(nxt == t){
ans = min(ans,w*2);
}
}
for(int i = 1; i<=n; i++){
LiChaoTree t(-(int)1e9, (int)1e9);
for(auto [_, nxt] : adj[i]){
t.add_line({-2 * h[nxt], dis[nxt] + h[nxt] * h[nxt]});
}
for(auto [_, nxt] : adj[i]){
int extra = dis2[nxt] + h[nxt] * h[nxt];
int v = t.query(h[nxt]);
v += extra;
ans = min(ans,v);
}
}
cout << ans/2;
if(ans%2==1){
cout << ".5\n";
}
else{
cout << ".0\n";
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3500kb
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: 0ms
memory: 3624kb
input:
5 5 1 5 1 2 10 10 4 1 2 2 3 2 4 3 5 4 5
output:
3.0
result:
ok found '3.0000000', expected '3.0000000', error '0.0000000'
Test #3:
score: 0
Accepted
time: 0ms
memory: 3484kb
input:
5 4 1 4 8 8 8 8 100 1 2 2 3 3 4 4 5
output:
0.0
result:
ok found '0.0000000', expected '0.0000000', error '-0.0000000'
Test #4:
score: -100
Wrong Answer
time: 0ms
memory: 3592kb
input:
2 1 1 2 0 100000 1 2
output:
10000000000.0
result:
wrong answer 1st numbers differ - expected: '0.0000000', found: '10000000000.0000000', error = '10000000000.0000000'