Submission #1302070

#TimeUsernameProblemLanguageResultExecution timeMemory
1302070uranium235Long Distance Coach (JOI17_coach)C++17
100 / 100
132 ms19180 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

template <class a, class b> ostream& operator<<(ostream &l, const pair<a, b> &r) {
    l << "(" << r.first << ", " << r.second << ")";
    return l;
}

template <class t, unsigned long int s> ostream& operator<<(ostream &l, const array<t, s> &r) {
    l << "[";
    for (int i = 0; i + 1 < s; i++) l << r[i] << ", ";
    if (s > 0) l << r[s - 1];
    l << "]";
    return l;
}

template <class t> ostream& operator<<(ostream &l, const vector<t> &r) {
    l << "{";
    for (int i = 0; i + 1 < r.size(); i++) l << r[i] << ", ";
    if (!r.empty()) l << r.back();
    l << "}";
    return l;
}

// kactl
struct Line {
	mutable ll k, m, p;
	bool operator<(const Line& o) const { return k < o.k; }
	bool operator<(ll x) const { return p < x; }
};

struct LineContainer : multiset<Line, less<>> {
	// (for doubles, use inf = 1/.0, div(a,b) = a/b)
	static const ll inf = LLONG_MAX;
	ll div(ll a, ll b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); }
	bool isect(iterator x, iterator y) {
		if (y == end()) return x->p = inf, 0;
		if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
		else x->p = div(y->m - x->m, x->k - y->k);
		return x->p >= y->p;
	}
	void add(ll k, ll m) {
		auto z = insert({k, m, 0}), y = z++, x = y;
		while (isect(y, z)) z = erase(z);
		if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
		while ((y = x) != begin() && (--x)->p >= y->p)
			isect(x, erase(y));
	}
	ll query(ll x) {
		assert(!empty());
		auto l = *lower_bound(x);
		return l.k * x + l.m;
	}
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll x, t;
    int n, m, w;
    cin >> x >> n >> m >> w >> t;
    vector<pair<ll, ll>> a(n + 1);
    for (int i = 0; i < n; i++) cin >> a[i].first;
    a[n].first = x;
    vector<pair<ll, int>> b(m);
    for (int i = 0; i < m; i++) cin >> b[i].first >> b[i].second;

    sort(b.begin(), b.end());
    for (int i = 0; i <= n; i++) {
        a[i].second = a[i].first / t;
        a[i].first = lower_bound(b.begin(), b.end(), make_pair(a[i].first % t, -1)) - b.begin() - 1;
    }
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end(), [](const pair<ll, ll> &l, const pair<ll, ll> &r) -> bool {
        // refilling stations do the same role -> minimize their start(a.second)
        return l.first == r.first;
    }), a.end());

    int ptr = a.size() - 1;
    ll suff = 0, dp = 0, suffC = 0;
    LineContainer cht;
    for (int i = m - 1; i >= 0; i--) {
        while (ptr >= 0 && a[ptr].first == i) {
            // refilling station -> add line
            // line x = { 1 * (dp - suffC + (a[ptr].second + 0) * suff), a[ptr].second + 0 };
            cht.add(-1 * a[ptr].second, -1 * (dp - (a[ptr].second + 0) * suff - suffC));
            // cout << "add" << endl;
            ptr--;
        }
        ll uses = (x - b[i].first) / t + 1;
        dp += uses * w;
        suff += w;
        suffC += b[i].second;
        
        if (!cht.empty()) {
            ll cons = -cht.query(suff) + suffC;
            // cout << i << " cons " << cons << endl;
            dp = min(dp, cons);
        }
        // cout << i << " dp " << dp << endl;

    }
    
    // driver
    dp += ((x / t) + 1) * w;
    // cout << a << endl;
    cout << dp << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...