結果

問題 No.2764 Warp Drive Spacecraft
ユーザー t98slidert98slider
提出日時 2024-05-17 23:15:46
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 6,953 bytes
コンパイル時間 2,517 ms
コンパイル使用メモリ 220,540 KB
実行使用メモリ 34,484 KB
最終ジャッジ日時 2024-05-17 23:15:57
合計ジャッジ時間 10,207 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 1 ms
6,944 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 WA -
testcase_04 AC 2 ms
6,944 KB
testcase_05 WA -
testcase_06 AC 2 ms
6,940 KB
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 RE -
testcase_11 RE -
testcase_12 RE -
testcase_13 RE -
testcase_14 WA -
testcase_15 WA -
testcase_16 AC 178 ms
34,484 KB
testcase_17 AC 187 ms
34,484 KB
testcase_18 AC 99 ms
30,336 KB
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 WA -
testcase_34 WA -
testcase_35 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

//min_ver
class LiChaoTree{
    struct Line{
        long long a, b;
        long long get(long long x){return a * x + b; }
        Line(long long a, long long b) : a(a), b(b) {}
    };
    struct Node {
        Node *left, *right;
        Line line;
        Node(Line line) : left(nullptr), right(nullptr), line(line) {}
    };
    const long long inf = 1ll << 60;
    const Line inf_line = Line{0, inf};

    Node *root;
    long long lx, rx;
    Node* _add_line(Node *nd, Line line, long long l, long long r){
        if(l == r) return nullptr;
        if(nd == nullptr) return new Node(line);
        long long m = (l + r) >> 1;

        bool left = (line.get(l) <= nd->line.get(l));
        bool mid = (line.get(m) <= nd->line.get(m));
        bool right = (line.get(r) <= nd->line.get(r));
        if(left && right)nd->line = line;
        if(left == right)return nd;
        if(mid) std::swap(nd->line, line);
        if(left != mid){
            nd->left = _add_line(nd->left, line, l, m);
        }else{
            nd->right = _add_line(nd->right, line, m, r);
        }
        return nd;
    }
    Node* _add_segment_line(long long a, long long b, Node *nd, Line line, long long l, long long r) {
        if(r <= a || b <= l) return nd;
        if(a <= l && r <= b) return _add_line(nd, line, l, r);
        if(nd == nullptr) nd = new Node(inf_line);
        long long m = (l + r) >> 1;
        nd->left = _add_segment_line(a, b, nd->left, line, l, m);
        nd->right = _add_segment_line(a, b, nd->right, line, m, r);
        return nd;
    }
    long long query(long long x, long long l, long long r){
        Node *nd = root;
        long long res = inf;
        while(r > l && nd != nullptr) {
            long long m = (l + r) >> 1;
            res = std::min(res, nd->line.get(x));
            if(x < m) {
                r = m;
                nd = nd->left;
            } else {
                l = m;
                nd = nd->right;
            }
        }
        return res;
    }
    public:
    // [xl, xr)
    LiChaoTree(long long lx, long long rx) : lx(lx), rx(rx), root(nullptr) {}
    void add_line(long long a, long long b) {
        Line line(a, b);
        root = _add_line(root, line, lx, rx);
    }
    void add_segment_line(long long a, long long b, long long l, long long r) {
        Line line = Line{a, b};
        root = _add_segment_line(l, r, root, line, lx, rx);
    }
    long long get(long long x) {
        return query(x, lx, rx);
    }
};

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
    public:
    segtree() : segtree(0) {}
    segtree(int n) : segtree(std::vector<S>(n, e())) {}
    segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        return d[p + size];
    }
    const S operator[](int p) const { return get(p); }
    S operator[](int p) { return get(p); }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

    private:
    int _n, size, log;
    std::vector<S> d;
    int ceil_pow2(int n) {
        int x = 0;
        while ((1U << x) < (unsigned int)(n)) x++;
        return x;
    }
    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

using S = pair<ll,int>;
S op(S lhs, S rhs){
    return min(lhs, rhs);
}
S e(){
    return make_pair(1ll << 60, -1);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    LiChaoTree LCT(0, 1 << 30);
    vector<S> tmp(n);
    for(int i = 0; i < n; i++){
        cin >> tmp[i].first;
        tmp[i].second = i;
    }
    segtree<S, op, e> seg(tmp);
    vector<vector<pair<int,ll>>> g(n);
    vector<ll> dp(n, 1ll << 60);
    priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;
    for(int i = 0; i < m; i++){
        int u, v, t;
        cin >> u >> v >> t;
        g[--u].emplace_back(--v, t);
        g[v].emplace_back(u, t);
    }
    dp[0] = 0;
    pq.emplace(0, 0);
    seg.set(0, e());
    while(!pq.empty()){
        auto [w, u] = seg.all_prod();
        ll d2 = 0;
        if(u != -1) d2 = LCT.get(w);
        if(u != -1 && d2 < pq.top().first){
            dp[u] = d2;
            pq.emplace(d2, u);
            seg.set(u, e());
            tie(w, u) = seg.all_prod();
            if(u == -1) d2 = 1ll << 62;
            else d2 = LCT.get(w);
        }
        auto [d, v] = pq.top();
        pq.pop();
        if(d > dp[v]) continue;
        LCT.add_line(tmp[v].first, d);
        for(auto &&[u, w] : g[v]){
            if(d + w >= dp[u]) continue;
            dp[u] = d + w;
            pq.emplace(dp[u], u);
        }
    }
    cout << dp.back() << '\n';
}
0