Submission #534238

#TimeUsernameProblemLanguageResultExecution timeMemory
534238wiwihoDungeon 3 (JOI21_ho_t5)C++14
100 / 100
1105 ms331344 KiB
#include <bits/stdc++.h>
#include <bits/extc++.h>

#define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define iter(a) a.begin(), a.end()
#define riter(a) a.rbegin(), a.rend()
#define lsort(a) sort(iter(a))
#define gsort(a) sort(riter(a))
#define pb(a) push_back(a)
#define eb(a) emplace_back(a)
#define pf(a) push_front(a)
#define ef(a) emplace_front(a)
#define pob pop_back()
#define pof pop_front()
#define mp(a, b) make_pair(a, b)
#define F first
#define S second
#define mt make_tuple
#define gt(t, i) get<i>(t)
#define tomax(a, b) ((a) = max((a), (b)))
#define tomin(a, b) ((a) = min((a), (b)))
#define topos(a) ((a) = (((a) % MOD + MOD) % MOD))
#define uni(a) a.resize(unique(iter(a)) - a.begin())
#define printv(a, b) {bool pvaspace=false; \
for(auto pva : a){ \
    if(pvaspace) b << " "; pvaspace=true;\
    b << pva;\
}\
b << "\n";}

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using tiii = tuple<int, int, int>;

const ll MOD = 1000000007;
const ll MAX = 2147483647;

template<typename A, typename B>
ostream& operator<<(ostream& o, pair<A, B> p){
    return o << '(' << p.F << ',' << p.S << ')';
}

ll ifloor(ll a, ll b){
    if(b < 0) a *= -1, b *= -1;
    if(a < 0) return (a - b + 1) / b;
    else return a / b;
}

ll iceil(ll a, ll b){
    if(b < 0) a *= -1, b *= -1;
    if(a > 0) return (a + b - 1) / b;
    else return a / b;
}

const int SZ = 20;
struct SparseTable{
    int n;
    vector<vector<ll>> st;
    vector<ll> a;
    int argmin(int x, int y){
        return a[x] <= a[y] ? x : y;
    }
    SparseTable(vector<ll>& a): a(a){
        n = a.size();
        n--;
        st.resize(SZ, vector<ll>(n + 1));
        iota(iter(st[0]), 0);
        for(int i = 1; i < SZ; i++){
            for(int j = 1; j + (1 << i) - 1 <= n; j++){
                st[i][j] = argmin(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
            }
        }
    }
    int query(int l, int r){
        int lg = __lg(r - l + 1);
        return argmin(st[lg][l], st[lg][r - (1 << lg) + 1]);
    }
};
struct SparseTableMax{
    int n;
    vector<vector<ll>> st;
    vector<ll> a;
    int argmin(int x, int y){
        return a[x] >= a[y] ? x : y;
    }
    SparseTableMax(vector<ll>& a): a(a){
        n = a.size();
        n--;
        st.resize(SZ, vector<ll>(n + 1));
        iota(iter(st[0]), 0);
        for(int i = 1; i < SZ; i++){
            for(int j = 1; j + (1 << i) - 1 <= n; j++){
                st[i][j] = argmin(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
            }
        }
    }
    ll query(int l, int r){
        int lg = __lg(r - l + 1);
        return a[argmin(st[lg][l], st[lg][r - (1 << lg) + 1])];
    }
};

struct Info{
    ll v1 = 0, v2 = 0;
};

Info merge(Info a, Info b, int lsz){
    Info c;
    c.v1 = a.v1 + b.v1;
    c.v2 = a.v2 + a.v1 * lsz + b.v2;
    return c;
}

struct Node{
    Info v;
    int l = -1, r = -1;
};

struct SegmentTree{
    
    vector<Node> st;
    int ts = 1;
    SegmentTree(): st(1e7) {}

    Info getv(int id){
        if(id == -1) return Info();
        return st[id].v;
    }

    void pull(int L, int R, int id){
        int M = (L + R) / 2;
        st[id].v = merge(getv(st[id].l), getv(st[id].r), R - M);
    }

    int modify(ll x, ll v, int L = 0, int R = 100000000, int id = 0){
        if(x < L || x > R) return id;
        if(id == -1) id = ts++;
        if(L == R){
            st[id].v.v1 += v;
            st[id].v.v2 += v;
            return id;
        }
        int M = (L + R) / 2;
        if(x <= M) st[id].l = modify(x, v, L, M, st[id].l);
        else st[id].r = modify(x, v, M + 1, R, st[id].r);
        pull(L, R, id);
        return id;
    }

    Info query(int l, int r, int L = 0, int R = 100000000, int id = 0){
        if(id == -1) return Info();
        if(l <= L && R <= r) return st[id].v;
        int M = (L + R) / 2;
        if(r <= M) return query(l, r, L, M, st[id].l);
        else if(l > M) return query(l, r, M + 1, R, st[id].r);
        else return merge(query(l, r, L, M, st[id].l), query(l, r, M + 1, R, st[id].r), r - M);
    }

    ll query(int x){
        return query(0, x).v2;
    }

};

int main(){
    StarBurstStream

    int n, m;
    cin >> n >> m;

    vector<ll> a(n + 2), b(n + 2);
    for(int i = 1; i <= n; i++) cin >> a[i + 1];
    SparseTableMax stmx(a);
    for(int i = 1; i <= n + 1; i++) a[i] += a[i - 1];
    for(int i = 1; i <= n; i++) cin >> b[i];

    vector<ll> xr(n + 1), xl(n + 2, -1);
    {
        deque<int> dq;
        dq.eb(n + 1);
        for(int i = n; i >= 1; i--){
            while(b[dq.back()] >= b[i]){
                dq.pob;
            }
            xr[i] = a[dq.back()];
            dq.eb(i);
        }
    }
    //cerr << "xr ";
    //printv(xr, cerr);
    
    SparseTable spt(b);

    vector<int> S(m + 1), T(m + 1), U(m + 1);
    vector<ll> ans(m + 1);
    vector<vector<int>> qry(n + 2);
    for(int i = 1; i <= m; i++){
        cin >> S[i] >> T[i] >> U[i];

        if(stmx.query(S[i] + 1, T[i]) > U[i]){
            ans[i] = -1;
            continue;
        }

        qry[S[i]].eb(i);
        int pos = lower_bound(a.begin() + 1, a.end(), max(a[S[i]], a[T[i]] - U[i])) - a.begin();
        int t = spt.query(pos, T[i]);
        //cerr << "test " << i << " " << pos << " " << t << "\n";
        ans[i] += (a[T[i]] - a[t]) * b[t];
        qry[t].eb(-i);
    }

    SegmentTree st;
    auto upd = [&](int i, int t){
        ll pos = xr[i] - a[i];
        st.modify(1, t);
        st.modify(pos + 1, -t);
        //cerr << "upd " << 1 << " " << pos << " " << t << "\n";
        if(xl[i] != -1){
            ll pos2 = a[i] - xl[i];
            st.modify(pos2 + 1, -t);
            ll pos3 = xr[i] - xl[i];
            st.modify(pos3 + 1, t);
            //cerr << "upd " << pos2 + 1 << " " << pos3 << " " << -t << "\n";
        }
        //for(int j = 0; j <= 10; j++) cerr << st.query(j) << " ";
        //cerr << "\n";
    };

    deque<int> dq;
    for(int i = n; i >= 1; i--){
        //cerr << "do " << i << "\n";
        while(!dq.empty() && b[dq.back()] >= b[i]){
            upd(dq.back(), -b[dq.back()]);
            xl[dq.back()] = a[i];
            upd(dq.back(), b[dq.back()]);
            dq.pob;
        }
        dq.eb(i);
        upd(i, b[i]);

        for(int j : qry[i]){
            //cerr << "query " << i << " " << U[abs(j)] << " " << st.query(U[abs(j)]) << "\n";
            if(j > 0) ans[j] += st.query(U[j]);
            else ans[-j] -= st.query(U[-j]);
        }
        
    }

    for(int i = 1; i <= m; 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...