제출 #470131

#제출 시각아이디문제언어결과실행 시간메모리
470131nhphucqtSafety (NOI18_safety)C++17
100 / 100
279 ms24672 KiB
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5+7;
int n, k, a[N];
long long addLef, addRig, res;
multiset<long long> lef, rig;
pair<long long, long long> segment[N];
long long trace[N];

long long getLef() {
    return *lef.rbegin() + addLef;
}

long long getRig() {
    return *rig.begin() + addRig;
}

void debug() {
    for (long long x : lef) cerr << x + addLef << ' ';
    for (long long x : rig) cerr << x + addRig << ' ';
    cerr << '\n';
}

void checkTrace() {
    long long sum = 0;
    for (int i = 1; i <= n; ++i) {
        assert(i==n || abs(trace[i]-trace[i+1]) <= k);
        sum += abs(a[i] - trace[i]);
    }
    assert(sum == res);
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    #ifdef NHPHUCQT
    freopen("demo.inp", "r", stdin);
    freopen("demo.out", "w", stdout);
    #endif

    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; ++i) {
        if ((lef.empty() && rig.empty()) || (getLef() <= a[i] && a[i] <= getRig())) {
            lef.insert(a[i] - addLef);
            rig.insert(a[i] - addRig);
        }
        else {
            if (a[i] < getLef()) {
                res += getLef() - a[i];
                lef.insert(a[i]-addLef);
                lef.insert(a[i]-addLef);
                rig.insert(getLef() - addRig);
                lef.erase(--lef.end());
            }
            else {
                res += a[i] - getRig();
                rig.insert(a[i]-addRig);
                rig.insert(a[i]-addRig);
                lef.insert(getRig() - addLef);
                rig.erase(rig.begin());
            }
        }
        segment[i] = {getLef(), getRig()};
        addLef -= k;
        addRig += k;
    }

    cout << res;

    // for (int i = 1; i <= n; ++i) {
    //     cerr << segment[i].first << ' ' << segment[i].second << '\n';
    // }

    trace[n] = segment[n].first;
    for (int i = n-1; i >= 1; --i) {
        long long l = trace[i+1] - k;
        long long r = trace[i+1] + k;
        if (segment[i].second < l) {
            trace[i] = l;
        }
        long long interLef = max(l, segment[i].first);
        long long interRig = min(r, segment[i].second);
        if (interLef <= interRig) {
            trace[i] = interLef;
        }
        else {
            if (l > segment[i].second) {
                trace[i] = l;
            }
            else {
                trace[i] = r;
            }
        }
    }

    // for (int i = 1; i <= n; ++i) {
    //     cerr << trace[i] << ' ';
    // }
    // cerr << '\n';

    checkTrace();

    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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...