제출 #1332832

#제출 시각아이디문제언어결과실행 시간메모리
1332832bronsonLong Distance Coach (JOI17_coach)C++20
100 / 100
135 ms23220 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Utilize 128-bit integer to prevent overflow on extreme limits.
typedef __int128_t int128;

struct Passenger {
    long long D, C;
    bool operator<(const Passenger& other) const {
        return D < other.D;
    }
};

struct Line {
    int128 m, c;
};
vector<Line> hull;

// Checks if the middle line l2 is redundant
bool bad(Line l1, Line l2, Line l3) {
    int128 num12 = l2.c - l1.c;
    int128 den12 = l1.m - l2.m;
    int128 num23 = l3.c - l2.c;
    int128 den23 = l2.m - l3.m;
    return num12 * den23 >= num23 * den12;
}

// Add a new line into the CHT lower envelope
void add(int128 m, int128 c) {
    Line l3 = {m, c};
    while (hull.size() >= 2 && bad(hull[hull.size()-2], hull.back(), l3)) {
        hull.pop_back();
    }
    hull.push_back(l3);
}

// Binary search the CHT for optimal crossing point
int128 query(int128 x) {
    if (hull.empty()) return 0;
    int low = 0, high = hull.size() - 1;
    int128 ans = hull[low].m * x + hull[low].c;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        int128 val_mid = hull[mid].m * x + hull[mid].c;
        ans = min(ans, val_mid);
        if (mid < (int)hull.size() - 1) {
            int128 val_next = hull[mid+1].m * x + hull[mid+1].c;
            if (val_next <= val_mid) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        } else {
            break;
        }
    }
    return ans;
}

// Support for standard stream output natively lacking __int128_t
void print(int128 x) {
    if (x == 0) { cout << 0 << "\n"; return; }
    if (x < 0) { cout << "-"; x = -x; }
    string s;
    while (x > 0) {
        s += (char)('0' + (x % 10));
        x /= 10;
    }
    reverse(s.begin(), s.end());
    cout << s << "\n";
}

int main() {
    // Fast I/O
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    long long X, N, M, W, T;
    if (!(cin >> X >> N >> M >> W >> T)) return 0;

    vector<long long> S_arr(N);
    for (int i = 0; i < N; ++i) {
        cin >> S_arr[i];
    }
    S_arr.push_back(X); // Destination counts as the final bounds parameter limit.

    vector<Passenger> passengers(M);
    for (int i = 0; i < M; ++i) {
        cin >> passengers[i].D >> passengers[i].C;
    }

    sort(passengers.begin(), passengers.end());

    vector<int128> S(M + 1, 0);
    for (int i = 1; i <= M; ++i) {
        S[i] = S[i-1] + passengers[i-1].C;
    }

    vector<long long> K(M + 1, -1);
    for (int m = 0; m <= N; ++m) {
        long long S_m = S_arr[m];
        long long k_m = (S_m + T - 1) / T - 1;
        long long W_m = (S_m - 1) % T + 1;

        int i_m = 0;
        int low = 0, high = M - 1;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (passengers[mid].D < W_m) {
                i_m = mid + 1;
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }

        if (i_m >= 1) {
            if (K[i_m] == -1 || k_m < K[i_m]) {
                K[i_m] = k_m;
            }
        }
    }

    auto R_p = [&](int p) -> int128 {
        long long D = passengers[p-1].D;
        long long num = X - D;
        return (int128)(num + T - 1) / T;
    };

    vector<int128> dp(M + 1, 0);
    add(0, 0);

    for (int i = 1; i <= M; ++i) {
        dp[i] = dp[i-1] + (int128)W * R_p(i);

        if (K[i] != -1) {
            int128 q = query((int128)K[i]);
            int128 cost_drop = q + (int128)W * K[i] * i + S[i];
            if (cost_drop < dp[i]) {
                dp[i] = cost_drop;
            }
        }

        int128 m_val = -(int128)W * i;
        int128 c_val = dp[i] - S[i];
        add(m_val, c_val);
    }

    // Tack on the driver baseline
    int128 driver_cost = (int128)W * ((X + T - 1) / T);
    int128 ans = dp[M] + driver_cost;

    print(ans);

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...