Submission #1181493

#TimeUsernameProblemLanguageResultExecution timeMemory
1181493patgraDungeon 3 (JOI21_ho_t5)C++20
100 / 100
760 ms127256 KiB
#include <bits/stdc++.h>

#define rep(a,b,c) for(auto a = (b); a != (c); a++)
#define repD(a,b,c) for(auto a = (b); a != (c); a--)
#define repIn(a, b) for(auto& a : (b))
#define repIn2(a, b, c) for(auto& [a, b] : (c))

constexpr bool dbg = 0;
#define DEBUG if constexpr(dbg)
#define DC DEBUG std::cerr
#define eol std::endl

#define ll long long
#define pb push_back

using namespace std;

constexpr ll inf = 1e18;
int n, q, maxLog;
vector<ll> dist, cost, answers, mrLeft, mrRight, prefSumDist;
vector<pair<pair<ll, ll>, pair<ll, ll>>> queries;
vector<vector<ll>> stMin, stMax;
vector<pair<pair<ll, ll>, ll>> queriesL;
vector<pair<pair<ll, ll>, pair<ll, ll>>> queriesM;
vector<ll> tr;
vector<pair<ll, ll>> t2;
vector<pair<int, int>> changes;
int tb;

void tAdd(ll i, ll x) {
    i += tb;
    while(i) tr[i] += x, i /= 2;
}

ll tQuery(ll l, ll r) {
    l += tb; r += tb;
    ll ret = tr[l];
    if(l != r) ret += tr[r];
    while(l / 2 != r / 2) {
        if(l % 2 == 0) ret += tr[l + 1];
        if(r % 2 == 1) ret += tr[r - 1];
        l /= 2; r /= 2;
    }
    return ret;
}

void tAdd2(ll i, ll a, ll b) {
    DC << "   tAdd2(" << i << ' ' << a << ' ' << b << ") " << eol;
    a *= cost[i]; b *= cost[i];
    i += tb;
    while(i) t2[i].first += a, t2[i].second += b, i /= 2;
}

ll tQuery2(ll l, ll r, ll u) {
    DC << "   tQuery2(" << l << ' ' << r << ' ' << u << ") -> ";
    l += tb;
    r += tb;
    ll ret = t2[l].first * u + t2[l].second;
    if(l != r) ret += t2[r].first * u + t2[r].second;
    while(l / 2 != r / 2) {
        if(l % 2 == 0) ret += t2[l + 1].first * u + t2[l + 1].second;
        if(r % 2 == 1) ret += t2[r - 1].first * u + t2[r - 1].second;
        l /= 2; r /= 2;
    }
    DC << ret << eol;
    return ret;
}

ll stMinQ(ll l, ll r) {
    assert(l <= r);
    int k = 63 - __builtin_clzll(r - l + 1);
    return min(stMin[l][k], stMin[r - (1 << k) + 1][k]);
}

ll stMaxQ(ll l, ll r) {
    assert(l <= r);
    int k = 63 - __builtin_clzll(r - l + 1);
    return max(stMax[l][k], stMax[r - (1 << k) + 1][k]);
}

ll findMinSt(ll L, ll R) {
    ll l = L - 1, m, r = R;
    ll mn = stMinQ(L, R);
    while(r - l > 1) {
        m = (l + r) / 2;
        if(mn == stMinQ(L, m)) r = m;
        else l = m;
    }
    return r;
}

ll calcBuy(ll s, ll t, ll u, ll i) {
    ll buy;
    ll mL, mR;
    if(mrLeft[i] >= s) mL = prefSumDist[i] - prefSumDist[mrLeft[i]];
    else mL = inf;
    if(mrRight[i] <= t) mR = prefSumDist[mrRight[i]] - prefSumDist[i];
    else mR = prefSumDist[t] - prefSumDist[i];
    if(u < min(mL, mR)) buy = u;
    else if(u < max(mL, mR)) buy = min(mL, mR);
    else if(u < mL + mR) buy = mR + mL - u;
    else buy = 0;
    DC << "  at " << i << "  l = " << mL << "  r = " << mR << "  u = " << u << "  buy = " << buy << eol;
    return buy;
}

void initTree2() {
    int s = 0, t = n;
    rep(i, 0, n) {
        ll mL, mR;
        if(mrLeft[i] >= s) mL = prefSumDist[i] - prefSumDist[mrLeft[i]];
        else mL = inf;
        if(mrRight[i] <= t) mR = prefSumDist[mrRight[i]] - prefSumDist[i];
        else mR = prefSumDist[t] - prefSumDist[i];
        tAdd2(i, 1, 0);
        changes.pb({min(mL, mR), i});
        changes.pb({max(mL, mR), i});
        changes.pb({mL + mR, i});
//          if(u < min(mL, mR)) buy = u;
//          else if(u < max(mL, mR)) buy = min(mL, mR);
//          else if(u < mL + mR) buy = mR + mL - u;
//          else buy = 0;
    }
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin >> n >> q;
    tb = 1 << (64 - __builtin_clzll(n));  
    tr.resize(2 * tb);
    t2.resize(2 * tb);
    dist.resize(n);
    cost.resize(n);
    queries.resize(q);
    answers.resize(q);
    rep(i, 0, n) cin >> dist[i];
    rep(i, 0, n) cin >> cost[i];
    rep(i, 0, q) {
        int s, t, u;
        cin >> s >> t >> u;
        s--; t--;
        queries[i] = {{u, i}, {s, t}};
    }

    maxLog = 32 - __builtin_clz(n + 2);
    stMin.resize(n, vector<ll>(maxLog, inf)), stMax.resize(n, vector<ll>(maxLog, -inf));; 
    rep(i, 0, n) stMin[i][0] = cost[i], stMax[i][0] = dist[i];
    rep(k, 1, maxLog) rep(i, 0, n) stMin[i][k] = min(stMin[i][k - 1], stMin[min(n - 1, i + (1 << (k - 1)))][k - 1]), stMax[i][k] = max(stMax[i][k - 1], stMax[min(n - 1, i + (1 << (k - 1)))][k - 1]);
    mrLeft.resize(n); mrRight.resize(n);
    rep(i, 0, n) {
        int l = -1, r = i, m;
        while(r - 1 > l) {
            m = (l + r) / 2;
            if(stMinQ(m, i - 1) <= cost[i]) l = m;
            else r = m;
        }
        mrLeft[i] = l;
        l = i, r = n;
        while(r - 1 > l) {
            m = (l + r) / 2;
            if(stMinQ(i + 1, m) < cost[i]) r = m;
            else l = m;
        }
        mrRight[i] = r;
        DC << "i " << i << " mrLeft " << mrLeft[i] << " mrRight " << mrRight[i] << eol;
    }

    prefSumDist.resize(n + 1);
    prefSumDist[0] = 0;
    rep(i, 0, n) prefSumDist[i + 1] = prefSumDist[i] + dist[i];
    repIn2(ui, st, queries) {
        auto [u, qi] = ui;
        auto [s, t] = st;
        DC << "query " << qi << "  " << s << ' ' << t << ' ' << u << eol;
        ll ans = 0;
        if(stMaxQ(s, t - 1) > u) { 
            answers[qi] = -1;
            continue;
        }
        ll l = s, r = t + 1, m;
        while(r - l > 1) { 
            m = (l + r) / 2;
            if(prefSumDist[m] - prefSumDist[s] > u) r = m;
            else l = m;
        }
        auto L = l;
        l = s, r = t + 1;
        while(r - l > 1) {
            m = (l + r) / 2;
            if(prefSumDist[t] - prefSumDist[m] > u) l = m;
            else r = m;
        }
        auto R = r;
        DC << " L " << L << "  R " << R << eol;
   
        l = s - 1, r = L;
        while(r - l > 1) {
            m = (l + r) / 2;
            if(stMinQ(s, L) == stMinQ(s, m)) r = m;
            else l = m;
        }
        auto whereMin = r;
        ans += cost[whereMin] * calcBuy(s, t, u, whereMin);
        if(whereMin > s) {
            queriesL.pb({{s, whereMin - 1}, qi});
            DC << "  added qL " << s << ' ' << whereMin - 1 << eol;
        }
        L = whereMin + 1;
        R = max(R, L);
        DC << " after L ans = " << ans << "; R = " << R << eol;

        if(R < t) {
            auto minn = stMinQ(R, t - 1);
            l = R - 1, r = t - 1;
            while(r - l > 1) {
                m = (l + r) / 2;
                if(stMinQ(R, m) == minn) r = m;
                else l = m;
            }
            whereMin = r;
            ans += cost[whereMin] * calcBuy(s, t, u, whereMin);
            R = whereMin;
        }
        DC << " after R ans = " << ans << eol;

        if(L < R && l < t) {
            queriesM.pb({{u, qi}, {L, R - 1}});
            DC << "  added qM " << L << ' ' << R - 1 << " at u=" << u << eol;
        }

        answers[qi] = ans;
    }

    ranges::sort(queriesL);
    stack<ll> stck;
    ll l = 0, r = n - 1;
    while(r >= l) {
        stck.push(findMinSt(l, r));
        tAdd(stck.top(), cost[stck.top()] * (prefSumDist[r + 1] - prefSumDist[stck.top()]));
        r = stck.top() - 1;
    }
    int qli = 0;
    rep(i, 0, n) {
        while(qli < (int)queriesL.size() && queriesL[qli].first.first == i) {
            auto [lr, qi] = queriesL[qli++];
            auto [mL, mR] = lr;
            auto ad = tQuery(mL, mR);
            DC << "After queryL (" << mL << ' ' << mR << ' ' << qi << ") answer +" << ad << eol;
            answers[qi] += ad;
        }
        if(stck.top() == i) {
            stck.pop();
            l = i + 1, r = (stck.empty() ? n - 1 : stck.top() - 1);
            tAdd(i, - cost[i] * (prefSumDist[r + 1] - prefSumDist[i]));
            while(r >= l) {
                stck.push(findMinSt(l, r));
                tAdd(stck.top(), cost[stck.top()] * (prefSumDist[r + 1] - prefSumDist[stck.top()]));
                r = stck.top() - 1;
            }
        }
    }

    ranges::sort(queriesM);
    auto ci = 0;
    initTree2();
    ranges::sort(changes);

    repIn2(ui, lr, queriesM) {
        auto [u, qi] = ui;
        auto [mL, mR] = lr;
        while(ci < (ll)changes.size() && changes[ci].first <= u) {
            auto [_, ii] = changes[ci++];
            tAdd2(ii, - t2[ii + tb].first / cost[ii], - t2[ii + tb].second / cost[ii]);

            ll mL2, mR2;
            ll s = 0, t = n;
            if(mrLeft[ii] >= s) mL2 = prefSumDist[ii] - prefSumDist[mrLeft[ii]];
            else mL2 = inf;
            if(mrRight[ii] <= t) mR2 = prefSumDist[mrRight[ii]] - prefSumDist[ii];
            else mR2 = prefSumDist[t] - prefSumDist[ii];
            if(u < min(mL2, mR2)) tAdd2(ii, 1, 0);
            else if(u < max(mL2, mR2)) tAdd2(ii, 0, min(mL2, mR2));
            else if(u < mL2 + mR2) tAdd2(ii, -1, mL2 + mR2);

        }
        auto ad = tQuery2(mL, mR, u);
        DC << "After queryM (" << u << ' ' << qi << ' ' << mL << ' ' << mR << ") answer +" << ad << eol;
        DEBUG {
            rep(i, mL, mR + 1) 
                assert(tQuery2(i, i, u) == calcBuy(0, n, u, i) * cost[i]);
        }
        answers[qi] += ad;
    }

    rep(i, 0, q) cout << answers[i] << '\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...