제출 #656634

#제출 시각아이디문제언어결과실행 시간메모리
656634minhnhatnoeFactories (JOI14_factories)C++17
100 / 100
3279 ms415444 KiB
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int LG = 20;
struct lcasparse{
    vector<pair<ll, int>> a[LG];
    vector<int> tin;
    vector<int> tout;
    void add_node(ll d, int v){
        if (tin[v] == -1) tin[v] = a[0].size();
        a[0].emplace_back(d, v);
    }
    void mark_out(int v){
        tout[v] = a[0].size()-1;
    }
    void lock(){
        for (int i=1; i<LG; i++){
            a[i].resize(a[0].size());
            for (int j=0; j + (1<<(i-1)) < a[i].size(); j++){
                a[i][j] = min(a[i-1][j], a[i-1][j + (1<<(i-1))]);
            }
        }
    }
    int query(int u, int v){
        if (tin[u] > tin[v]) swap(u, v);
        int lg2 = 31 - __builtin_clz(tin[v] - tin[u] + 1);
        return min(a[lg2][tin[u]], a[lg2][tin[v] - (1<<lg2) + 1]).second;
    }
    void init(int n){
        tin.resize(n, -1);
        tout.resize(n, -1);
    }
    ll get_depth(int v){
        return a[0][tin[v]].first;
    }
    bool is_par(int p, int v){
        return tin[p] <= tin[v] && tin[v] <= tout[p];
    }
} lca;
vector<vector<pair<int, ll>>> g;
void dfslca(int v, int p, ll d){
    lca.add_node(d, v);
    for (auto [u, ed]: g[v]){
        if (u == p) continue;
        dfslca(u, v, ed + d);
        lca.add_node(d, v);
    }
    lca.mark_out(v);
}
void Init(int N, int A[], int B[], int D[]){
    g.resize(N);
    for (int i=0; i<N-1; i++){
        int u = A[i], v = B[i];
        int d = D[i];
        g[u].emplace_back(v, d);
        g[v].emplace_back(u, d);
    }
    lca.init(N);
    dfslca(0, -1, 0);
    lca.lock();
}
struct testcase{
    vector<int> &from, &to;
    vector<bool> is_src;
    vector<int> nodes;
    void get_nodes(){
        for (int i=nodes.size()-1; i; i--){
            nodes.push_back(lca.query(nodes[i-1], nodes[i]));
        }
        sort(nodes.begin(), nodes.end(), [](int &a, int &b){
            return lca.tin[a] < lca.tin[b];
        });
        nodes.resize(unique(nodes.begin(), nodes.end()) - nodes.begin());
    }
    vector<vector<pair<int, ll>>> vtr;
    void build_tree(){
        vtr.resize(nodes.size());
        // rid, vid
        vector<pair<int, int>> st;
        for (int i=0; i < nodes.size(); i++){
            int v = nodes[i];
            while (st.size() && !lca.is_par(st.back().first, v)){
                st.pop_back();
            }
            if (st.size()){
                vtr[st.back().second].emplace_back(i,
                    lca.get_depth(v) - lca.get_depth(st.back().first));
            }
            st.emplace_back(v, i);
        }
    }
    vector<ll> dp;
    void dfs1(int v, int p){
        if (is_src[v] == 1) dp[v] = 0;
        else dp[v] = 1e15;
        for (pair<int, ll> e: vtr[v]){
            assert((e.first != p));
            dfs1(e.first, v);
            dp[v] = min(dp[v], dp[e.first] + e.second);
        }
    }
    void dfs2(int v, int p){
        for (pair<int, ll> e: vtr[v]){
            dp[e.first] = min(dp[e.first], dp[v] + e.second);
            dfs2(e.first, v);
        }
    }
    ll result = LLONG_MAX;
    void mark_src(){
        sort(from.begin(), from.end(), [](int &a, int &b){
            return lca.tin[a] < lca.tin[b];
        });
        is_src.resize(nodes.size());
        for (int nptr = 0, i=0; i < from.size(); i++){
            while (nodes[nptr] != from[i]) nptr++;
            is_src[nptr] = 1;
        }
    }
    void get_result(){
        result = LLONG_MAX;
        sort(to.begin(), to.end(), [](int &a, int &b){
            return lca.tin[a] < lca.tin[b];
        });
        is_src.resize(nodes.size());
        for (int nptr = 0, i=0; i < to.size(); i++){
            while (nodes[nptr] != to[i]) nptr++;
            result = min(result, dp[nptr]);

        }
    }
    testcase(vector<int> &from, vector<int> &to): from(from), to(to) {
        nodes = to;
        for (int v: from){
            nodes.push_back(v);
        }
        sort(nodes.begin(), nodes.end(), [](int &a, int &b){
            return lca.tin[a] < lca.tin[b];
        });
        get_nodes();
        mark_src();
        build_tree();
        dp.resize(nodes.size());
        dfs1(0, -1);
        dfs2(0, -1);
        get_result();
    }
};
ll Query(int S, int X[], int T, int Y[]){
    vector<int> from(X, X + S);
    vector<int> to(Y, Y + T);
    return testcase(from, to).result;
}

컴파일 시 표준 에러 (stderr) 메시지

factories.cpp: In member function 'void lcasparse::lock()':
factories.cpp:20:42: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   20 |             for (int j=0; j + (1<<(i-1)) < a[i].size(); j++){
      |                           ~~~~~~~~~~~~~~~^~~~~~~~~~~~~
factories.cpp: In member function 'void testcase::build_tree()':
factories.cpp:81:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   81 |         for (int i=0; i < nodes.size(); i++){
      |                       ~~^~~~~~~~~~~~~~
factories.cpp: In member function 'void testcase::mark_src()':
factories.cpp:115:35: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  115 |         for (int nptr = 0, i=0; i < from.size(); i++){
      |                                 ~~^~~~~~~~~~~~~
factories.cpp: In member function 'void testcase::get_result()':
factories.cpp:126:35: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  126 |         for (int nptr = 0, i=0; i < to.size(); i++){
      |                                 ~~^~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...