Submission #991211

#TimeUsernameProblemLanguageResultExecution timeMemory
991211model_codeConstruction Project 2 (JOI24_ho_t2)C++17
100 / 100
863 ms57120 KiB
// 別解

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;

using P = pair<long long, int>;

struct edge{
    int to;
    long long cost;
};

template< typename S, S (*op)(S, S), S (*e)() >
struct segmenttree{
    private:
    int _n;
    std::vector<S> node;

    public:
    segmenttree() = default;
      
    segmenttree(int n){
        _n = 1;
        while(_n < n){
            _n *= 2;
        }
        node.resize(2 * _n, e());
    }
    segmenttree(std::vector<S> &v){
        int n = v.size();
        _n = 1;
        while(_n < n){
            _n *= 2;
        }
        node.resize(2 * _n, e());
        for(int i = 0; i < n; i++){
            set(i, v[i]);
        }
    }

    // [i] <- val
    void set(int i, S val){
        i += _n;
        node[i] = val;
        while(i > 1){
            i >>= 1;
            node[i] = op(node[2 * i], node[2 * i + 1]);
        }
    }

    // [i] <- op([i],val)
    void update(int i, S val){
        i += _n;
        node[i] = op(node[i], val);
        while(i > 1){
            i >>= 1;
            node[i] = op(node[2 * i], node[2 * i + 1]);
        }
    }

    S get(int i){
        i += _n;
        return node[i];
    }

    S prod(int l,int r){
        S pdl=e(), pdr=e();
        l += _n;
        r += _n;

        while(l < r){
            if(l & 1){
              pdl = op(pdl, node[l++]);
            }
            if(r & 1){
                pdr = op(node[--r], pdr);
            }
            l >>= 1;
            r >>= 1;
        }

        return op(pdl, pdr);
    };
};

int op(int a, int b){
    return a + b;
}

int e(){
    return 0;
}

constexpr long long inf = 1e18;

int main(){
    int n, m;
    cin >> n >> m;
    
    int s, t;
    long long l, k;
    cin >> s >> t >> l >> k;
    s--;
    t--;

    vector<vector<edge>> g(n);
    for(int i = 0; i < m; i++){
        int a, b;
        long long c;
        cin >> a >> b >> c;
        a--;
        b--;

        g[a].push_back({b, c});
        g[b].push_back({a, c});
    }

    priority_queue<P, vector<P>, greater<P>> que;
    vector<long long> dist_from_s(n, inf), dist_from_t(n, inf);

    dist_from_s[s] = 0;
    que.push({0, s});
    while(!que.empty()){
        auto [dist, now] = que.top();
        que.pop();

        if(dist_from_s[now] < dist){
            continue;
        }

        for(auto [nxt, c]: g[now]){
            if(dist_from_s[nxt] > dist + c){
                dist_from_s[nxt] = dist + c;
                que.push({dist + c, nxt});
            }
        }
    }

    dist_from_t[t] = 0;
    que.push({0, t});
    while(!que.empty()){
        auto [dist, now] = que.top();
        que.pop();

        if(dist_from_t[now] < dist){
            continue;
        }

        for(auto [nxt, c]: g[now]){
            if(dist_from_t[nxt] > dist + c){
                dist_from_t[nxt] = dist + c;
                que.push({dist + c, nxt});
            }
        }
    }

    if(dist_from_s[t] <= k){
        cout << (long long)(n) * (n - 1) / 2 << endl;
        return 0;
    }

    vector<long long> val = dist_from_s;
    for(int i = 0; i < n; i++){
        val.emplace_back(dist_from_t[i]);
    }
    sort(val.begin(), val.end());

    map<long long, int> index;
    for(int i = 0; i < 2 * n; i++){
        index[val[i]] = i;
    }

    segmenttree<int, op, e> seg1(2 * n), seg2(2 * n);
    long long ans = 0;

    for(int i = 0; i < n; i++){
        long long ok = k - l - dist_from_s[i];
        ans += seg2.prod(0, lower_bound(val.begin(), val.end(), ok + 1) - val.begin());
        ok = k - l - dist_from_t[i];
        ans += seg1.prod(0, lower_bound(val.begin(), val.end(), ok + 1) - val.begin());
        
        seg1.update(index[dist_from_s[i]], 1);
        seg2.update(index[dist_from_t[i]], 1);
    }

    cout << ans << endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...