Submission #1183993

#TimeUsernameProblemLanguageResultExecution timeMemory
1183993jerzykDungeon 3 (JOI21_ho_t5)C++20
100 / 100
460 ms112304 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define st first
#define nd second
typedef long long ll;
typedef long double ld;
const ll I = 1000LL * 1000LL * 1000LL * 1000LL * 10LL;
const int II = 2 * 1000 * 1000 * 1000;
const ll M = 1000LL * 1000LL * 1000LL + 7LL;
const int N = 1<<18;
int rmq[N][20];

int jp[N][20], jpl[N][20];
ll jps[N][20];

ll dis[N], sump[N], cst[N];
int l[N], r[N];
vector<int> cq;


ll drz[2 * N], laz[2 * N], il[2 * N];

pair<ll, int> que[N];
pair<int, int> ran[N];
ll answer[N];
int cnt[N];

pair<int, ll> Jump(int a, ll d)
{
    int st = a;
    ll s = 0LL;
    //cerr << "J " << d << "\n";
    for(int i = 18; i >= 0; --i)
        if(sump[jp[a][i] - 1] - sump[st - 1] <= d)
        {
            //cerr << "j: " << a << " " << "\n";
            s += jps[a][i];
            a = jp[a][i];
        }
    return make_pair(a, s);
}

int JP2(int a, ll d)
{
    int st = a;
    for(int i = 18; i >= 0; --i)
        if(sump[st] - sump[jpl[a][i] - 1] <= d)
            a = jpl[a][i];
    return a;
}

int MaQue(int a, int b)
{
    int r = 31 - __builtin_clz(b - a + 1);
    return max(rmq[a][r], rmq[b - (1<<r) + 1][r]);
}

inline void Push(int v)
{
    for(int nv = v * 2; nv <= v * 2 + 1; ++nv)
    {
        drz[nv] += laz[v] * il[nv];
        laz[nv] += laz[v];
    }
    laz[v] = 0;
}

void Change(int v, int val)
{
    int x = 1;
    for(int i = 17; i >= 0; --i)
    {
        Push(x);
        x *= 2;
        if(v & (1<<i)) ++x;
    }
    il[x] += val;
    x /= 2;
    while(x > 0)
    {
        il[x] = il[x * 2] + il[x * 2 + 1];
        x /= 2;
    }
}

ll Query(int v, int p, int k, int pz, int kz)
{
    if(p > kz || k < pz) return 0LL;
    if(p >= pz && k <= kz) return drz[v];
    Push(v);
    ll a;
    a = Query(v * 2, p, (p + k) / 2, pz, kz);
    a += Query(v * 2 + 1, (p + k) / 2 + 1, k, pz, kz);
    return a;
}

void Upd(ll x)
{
    drz[1] += il[1] * x;
    laz[1] += x;
}

void DoQ(int n, int q)
{
    vector<pair<ll, int>> cha;
    ll lst = 0LL;
    for(int i = 1; i <= n; ++i)
    {
        cnt[i] = 0;
        ll d1 = sump[r[i] - 1] - sump[i - 1];
        ll d2 = I;
        if(l[i] != 0)
            d2 = sump[i - 1] - sump[l[i] - 1];
        //cout << i << " l: " << l[i] << " " << d2 << " r: " << r[i] << " " << d1 << "\n";
        cha.pb(make_pair(d1, i));
        cha.pb(make_pair(d2, i));
        cha.pb(make_pair(d1 + d2, i));
    }
    //cerr << "xd\n";
    sort(cha.begin(), cha.end());
    int j = 0;
    for(int i = 1; i <= q; ++i)
    {
        int p = ran[que[i].nd].st, k = ran[que[i].nd].nd;
        while(j < (int)cha.size() && (ll)que[i].st >= cha[j].st)
        {
            //cout << "Cha: " << cha[j].st << "\n"
            Upd(cha[j].st - lst);
            lst = cha[j].st;
            if(cnt[cha[j].nd] < 2)
                Change(cha[j].nd, -cst[cha[j].nd]);
            else
                Change(cha[j].nd, cst[cha[j].nd]);
            ++cnt[cha[j].nd];
            ++j;
        }
        Upd(que[i].st - lst);
        lst = que[i].st;
        int xd = MaQue(p, k - 1);
        if(que[i].st >= xd)
        {
            ll ans = 0LL;
            pair<int, ll> xd;
            xd = Jump(p, min((ll)que[i].st, sump[k - 1] - sump[p - 1]));
            int cur = xd.st;
            int cur2 = JP2(k - 1, min((ll)que[i].st, sump[k - 1] - sump[cur - 1]));
            if(cur2 < cur) cur2 = cur;
            ans = xd.nd;
            //cerr << "S: " << ans << " " << cur << " " << cur2 << " " << jpl[cur2][0] << "\n";
            //cur2 = l[cur2];
            if(cur != cur2)
            {
                ll mn = min(min((ll)que[i].st, sump[k - 1] - sump[cur - 1]), sump[r[cur] - 1] - sump[cur - 1]);
                ans += mn * cst[cur];
            }

            if(cur2 != k)
            {
                ll mn = sump[k - 1] - sump[cur2 - 1];
                ll df = 0LL;
                if(l[cur2] >= p)
                    df = max(0LL, min(que[i].st, sump[k - 1] - sump[l[cur2] - 1]) - (sump[cur2 - 1] - sump[l[cur2] - 1]));
                mn -= df;
                ans += mn * cst[cur2];
            }
            //cerr << ans << "\n";
            if(cur + 1 <= cur2 - 1)
                ans += Query(1, 0, N - 1, cur + 1, cur2 - 1);
            //cerr << i << " " << cur << " " << ans << "\n";
            answer[que[i].nd] = ans;
        }
        else
            answer[que[i].nd] = -1;
    }
}

void Solve()
{
    int n, q;
    cin >> n >> q;
    for(int i = 1; i <= n; ++i)
    {
        cin >> dis[i];
        rmq[i][0] = dis[i];
        sump[i] = sump[i - 1] + dis[i];
    }
    //cerr << "xd\n";
    for(int i = n; i >= 1; --i)
        for(int j = 1; i + (1<<j) - 1 <= n; ++j)
            rmq[i][j] = max(rmq[i][j - 1], rmq[i + (1<<(j - 1))][j - 1]);
    //cerr << "xd\n";
    cst[0] = -II;
    cq.pb(0);
    for(int i = 1; i <= n; ++i)
    {
        cin >> cst[i]; il[i + N] = cst[i];
        while(cst[cq.back()] > cst[i])
            cq.pop_back();
        l[i] = cq.back();
        jpl[i][0] = l[i];
        cq.pb(i);
    }
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= 18; ++j)
            jpl[i][j] = jpl[jpl[i][j - 1]][j - 1];
    for(int i = N - 1; i >= 1; --i) il[i] = il[i * 2] + il[i * 2 + 1];
    cq.clear();
    cst[n + 1] = -II;
    cq.pb(n + 1);
    //cerr << "xd\n";
    for(int i = n; i >= 1; --i)
    {
        while(cst[cq.back()] >= cst[i])
            cq.pop_back();
        r[i] = cq.back();
        cq.pb(i);
        jp[i][0] = r[i];
        jps[i][0] = (sump[r[i] - 1] - sump[i - 1]) * cst[i];
    }
    jp[n + 1][0] = n + 1;
    for(int i = n + 1; i >= 1; --i)
        for(int j = 1; j <= 18; ++j)
        {
            jp[i][j] = jp[jp[i][j - 1]][j - 1];
            jps[i][j] = jps[i][j - 1] + jps[jp[i][j - 1]][j - 1];
        }
    for(int i = 1; i <= q; ++i)
    {
        cin >> ran[i].st >> ran[i].nd;
        cin >> que[i].st;
        que[i].nd = i;
    }
    sort(que + 1, que + 1 + q);
    DoQ(n, q);
    for(int i = 1; i <= q; ++i)
        cout << answer[i] << "\n";
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    Solve();

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