Submission #1302543

#TimeUsernameProblemLanguageResultExecution timeMemory
1302543_callmelucianFire (JOI20_ho_t5)C++17
100 / 100
176 ms51908 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

const int mn = 2e5 + 5;
int prv[mn], nxt[mn], A[mn], B[mn], G[mn];
vector<tuple<int,int,int>> qry[mn], update[mn];
ll S[mn], ans[mn];

struct BIT {
    vector<ll> idp, idpmul, dp, dpmul;
    BIT (int sz) : idp(sz + 1), idpmul(sz + 1), dp(sz + 1), dpmul(sz + 1) {}

    int p (int k) { return k & -k; }

    void updateIDP (int pos, ll delta) {
        for (int k = pos; k < idp.size(); k += p(k))
            idp[k] += delta, idpmul[k] += delta * S[pos];
    }

    void updateDP (int pos, ll delta) {
        for (int k = pos; k < dp.size(); k += p(k))
            dp[k] += delta, dpmul[k] += delta * S[pos];
    }

    ll getNode (int k, ll T) { return idp[k] + dp[k] * T; }
    ll preSum (int k, ll T) {
        ll ans = 0;
        for (; k; k -= p(k))
            ans += idpmul[k] + dpmul[k] * T;
        return ans;
    }

    ll sumFirstK (int target, ll T) {
        if (target == 0) return 0;
        int position = 0, sumCur = 0;
        for (int mask = 1 << 17; mask; mask >>= 1) {
            if ((position | mask) >= idp.size()) continue;
            if (sumCur + getNode(position | mask, T) < target)
                position |= mask, sumCur += getNode(position, T);
        }
        return preSum(position, T) + (target - sumCur) * S[position + 1];
    }
};

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

    // input
    int N, Q; cin >> N >> Q;
    for (int i = 1; i <= N; i++) cin >> S[i];
    for (int i = 0; i < Q; i++) {
        int T, L, R; cin >> T >> L >> R;
        qry[T].emplace_back(L, R, i);
    }

    // precompute prv, nxt
    vector<int> st;
    for (int i = 1; i <= N; i++) {
        while (st.size() && S[st.back()] < S[i]) st.pop_back();
        prv[i] = (st.size() ? st.back() : -1e9), st.push_back(i);
    }
    
    st.clear();
    for (int i = N; i >= 1; i--) {
        while (st.size() && S[st.back()] <= S[i]) st.pop_back();
        nxt[i] = (st.size() ? st.back() : 1e9), st.push_back(i);
    }

    // compute A, B, G and create sweep-line events
    for (int i = 1; i <= N; i++) {
        A[i] = min(nxt[i] - i, i - prv[i]);
        B[i] = max(nxt[i] - i, i - prv[i]);
        G[i] = nxt[i] - prv[i];

        // update independent part
        update[0].emplace_back(i, 1, 0);
        if (A[i] <= N) update[A[i]].emplace_back(i, A[i] - 1, 0);
        if (B[i] <= N) update[B[i]].emplace_back(i, G[i] - 1 - A[i], 0);
        if (G[i] <= N) update[G[i]].emplace_back(i, 0 - G[i] + 1, 0);

        // update dependent part
        update[0].emplace_back(i, 1, 1);
        if (A[i] <= N) update[A[i]].emplace_back(i, -1, 1);
        if (B[i] <= N) update[B[i]].emplace_back(i, -1, 1);
        if (G[i] <= N) update[G[i]].emplace_back(i, 1, 1);
    }

    // perform sweep line
    BIT tree(N);
    for (int T = 0; T <= N; T++) {
        // process updates
        for (auto [idx, delta, dpd] : update[T]) {
            if (dpd) tree.updateDP(idx, delta);
            else tree.updateIDP(idx, delta);
        }

        // process queries
        for (auto [L, R, idx] : qry[T])
            ans[idx] = tree.sumFirstK(R, T) - tree.sumFirstK(L - 1, T);
    }

    // output queries
    for (int i = 0; i < Q; i++) cout << ans[i] << "\n";

    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...