Submission #1219475

#TimeUsernameProblemLanguageResultExecution timeMemory
1219475Double_SlashFish 2 (JOI22_fish2)C++20
100 / 100
1143 ms39472 KiB
#include <bits/stdc++.h>
 
using namespace std;
using ll = long long;
using pint = pair<int, int>;
using pll = pair<ll, ll>;
using Val = array<int, 3>;
 
const int INF = 1e9;
int n, q;
ll x[100002];
set<int> s[100001], e[100001];
 
pll operator+(const pll &a, const pll &b) { return {a.first + b.first, max(a.second, a.first + b.second)}; }
 
void operator+=(pll &p, ll v) { p.first += v, p.second += v; }
 
struct PreMin {
    int n = 1;
    vector<pll> st;
 
    PreMin(int _n) {
        while (n < _n) n <<= 1;
        st.resize(n << 1);
    }
 
    void update(int i, ll v, bool point = false) {
        if (point) update(i + 1, -v, false);
        for (st[i += n] += v; i >>= 1;) st[i] = st[i << 1] + st[i << 1 | 1];
    }
 
    ll query(int r) {
        ll ret = 0;
        for (r += n; r & (r - 1); r >>= 1) {
            if (r & 1) ret += st[--r].first;
        }
        return ret;
    }
 
    int walksuf(int l, ll x) {
        x -= query(l);
        for (l += n;; l >>= 1) {
            if (l & 1) {
                if (st[l].second > x) {
                    while (l < n) {
                        if (st[l <<= 1].second <= x) {
                            x -= st[l].first;
                            l ^= 1;
                        }
                    }
                    return l - n;
                } else x -= st[l++].first;
                if (not (l & (l - 1))) return n;
            }
        }
    }
};
 
Val operator+(const Val &a, const Val &b) {
    if (a[1] < a[0] + b[1]) return {a[0] + b[0], a[1], a[2]};
    else if (a[0] + b[1] < a[1]) return {a[0] + b[0], a[0] + b[1], b[2]};
    else return {a[0] + b[0], a[1], a[2] + b[2]};
}
 
void operator+=(Val &v, int x) { v[0] += x, v[1] += x; }
 
struct CntPreMin {
    int n;
    vector<Val> st;
 
    CntPreMin(int n) : n(n), st(n << 1, {0, 0, 1}) {}
 
    void update(int i, int v) {
        for (st[i += n] += v; i >>= 1;) st[i] = st[i << 1] + st[i << 1 | 1];
    }
 
    Val query(int l, int r) {
        Val lagg{0, INF}, ragg{INF, INF};
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) lagg = lagg + st[l++];
            if (r & 1) ragg = st[--r] + ragg;
        }
        return lagg + ragg;
    }
};
 
int main() {
    cin >> n;
    PreMin leat{n + 1}, reat{n + 2}, ranges{n + 2};
    leat.update(n - 1, x[0] = 1e18);
    reat.update(n, x[n + 1] = 1e18);
    auto ps = [&] (int i) { return i ? x[i + 1] - reat.query(i + 1) : 0ll; };
    CntPreMin st{n + 2};
    for (int i = 1; i <= n; ++i) e[i].emplace(0);
    auto rem = [&] (int l, int r) {
        if (r == *e[l].rbegin()) ranges.update(l, *next(e[l].rbegin()) - r, true);
        e[l].erase(r);
        s[r].erase(l);
        st.update(l, -1);
        st.update(r + 1, 1);
    };
    auto add = [&] (int i) {
        for (int l = i, r = i;;) {
            for (ll psl = ps(l - 1), psr = ps(r);;) {
                if (psr - psl >= x[r + 1]) psr = ps(r = reat.walksuf(r, -psl));
                else if (psr - psl >= x[l - 1]) psl = ps((l = n - leat.walksuf(n - l, psr)) - 1);
                else break;
            }
            if (l == 1 and r == n) break;
            if (not e[l].contains(r)) {
                if (r > *e[l].rbegin()) ranges.update(l, r - *e[l].rbegin(), true);
                e[l].emplace(r);
                s[r].emplace(l);
                st.update(l, 1);
                st.update(r + 1, -1);
            }
            if (x[l - 1] < x[r + 1]) --l;
            else ++r;
        }
    };
    auto upd = [&] (int a, int b = 0) {
        if (not b) cin >> b;
        reat.update(a, -(1 + (a >= 2)) * (b -= x[a]));
        if (a >= 2) reat.update(a - 1, b);
        if (a < n) {
            leat.update(0, b * (1 + (a == n - 1)));
            leat.update(n - a, -2 * b);
            if (a < n - 1) leat.update(n - (a + 1), b);
        }
        x[a] += b;
        if (b < 0) {
            if (a > 1) {
                ll P = ps(a - 1);
                for (auto it = s[a - 1].end(); it != s[a - 1].begin();) {
                    if (int l = *prev(it); P - ps(l - 1) >= min(x[a], x[l - 1])) rem(*prev(it), a - 1);
                    else --it;
                }
            }
            add(a);
            if (a < n) {
                ll P = ps(a);
                for (auto it = e[a + 1].end(); *prev(it);) {
                    if (int r = *prev(it); ps(r) - P >= min(x[a], x[r + 1])) rem(a + 1, *prev(it));
                    else --it;
                }
            }
        } else if (b > 0) {
            if (a > 1) add(a - 1);
            for (int l = 0; l < a;) {
                l = ranges.walksuf(l + 1, a - 1);
                if (l > a) break;
                ll P = ps(l - 1);
                for (auto it = e[l].end(); *prev(it);) {
                    if (int r = *prev(it); ps(r) - P >= min(x[l - 1], x[r + 1])) rem(l, r);
                    else --it;
                }
            }
            if (a < n) add(a + 1);
        }
    };
    for (int i = 1; i <= n; ++i) upd(i);
    cin >> q;
    while (q--) {
        int t, a, b;
        cin >> t >> a >> b;
        if (t == 1) upd(a, b);
        else {
            int l = a;
            for (ll P = ps(a - 1);;) {
                int i = reat.walksuf(l, -P);
                if (i >= b) break;
                l = i + 1;
            }
            int r = b;
            for (ll P = ps(b);;) {
                int i = n - leat.walksuf(n - r, P);
                if (i <= a) break;
                r = i - 1;
            }
            cout << st.query(l, r + 1)[2] << endl;
        }
    }
}
#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...