QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#383236#5540. City Hallkevinyang#WA 0ms3624kbC++174.8kb2024-04-09 06:26:152024-04-09 06:26:15

Judging History

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

  • [2024-04-09 06:26:15]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3624kb
  • [2024-04-09 06:26:15]
  • 提交

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'