Submission #933496

#TimeUsernameProblemLanguageResultExecution timeMemory
933496ksujay2Fish 2 (JOI22_fish2)C++17
100 / 100
1544 ms15192 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MXN = 1e5 + 1;
const ll INF = 1e18;

// count min segtree
const int SEGTSZ = 2 << 17;
struct D {
    int cnt, mn, lz;
} segt[SEGTSZ];


void pull(int s) {
    segt[s].mn = min(segt[2 * s].mn, segt[2 * s + 1].mn);
    segt[s].cnt = (segt[2 * s].mn == segt[s].mn ? segt[2 * s].cnt : 0) + (segt[2 * s + 1].mn == segt[s].mn ? segt[2 * s + 1].cnt : 0);
    segt[s].mn += segt[s].lz;
}

void build(int s, int lb, int rb) {
    if(lb == rb) {
        segt[s].cnt = 1;
        return;
    }
    int m = (lb + rb) / 2;
    build(2 * s, lb, m);
    build(2 * s + 1, m + 1, rb);
    pull(s);
}

void upd(int u, int l, int r, int s, int lb, int rb) {
    l = max(lb, l), r = min(rb, r);    
    if(r < l) return;
    if(l == lb && r == rb) {
        segt[s].lz += u;
        segt[s].mn += u;
        return;
    }
    int m = (lb + rb) / 2;
    upd(u, l, r, 2 * s, lb, m);
    upd(u, l, r, 2 * s + 1, m + 1, rb);
    pull(s);
}

pair<int, int> query(int l, int r, int s, int lz, int lb, int rb) {
    l = max(lb, l), r = min(rb, r);    
    if(r < l) return {1e9, 0};
    if(l == lb && r == rb) {
        return {segt[s].mn + lz, segt[s].cnt};
    }
    int m = (lb + rb) / 2;
    lz += segt[s].lz;
    auto lres = query(l, r, 2 * s, lz, lb, m);
    auto rres = query(l, r, 2 * s + 1, lz, m + 1, rb);
    if(lres.first > rres.first) swap(rres, lres);
    lres.second += (lres.first == rres.first) ? rres.second : 0;
    return lres;
}

// go as left / right as possible
struct D2 {
    ll sm, mn;
} lsegt[SEGTSZ], rsegt[SEGTSZ];

void lupd(ll u, int k, int s, int lb, int rb) {
    if(k == lb && rb == k) {
        lsegt[s].sm += u;
        lsegt[s].mn += u;
        return;
    }
    int m = (lb + rb) / 2;
    if(k <= m) {
        lupd(u, k, 2 * s, lb, m);
    } else {
        lupd(u, k, 2 * s + 1, m + 1, rb);
    }
    lsegt[s].mn = min(lsegt[2 * s].mn, lsegt[2 * s].sm + lsegt[2 * s + 1].mn);
    lsegt[s].sm = lsegt[2 * s].sm + lsegt[2 * s + 1].sm;
}

void rupd(ll u, int k, int s, int lb, int rb) {
    if(k == lb && rb == k) {
        rsegt[s].sm += u;
        rsegt[s].mn += u;
        return;
    }
    int m = (lb + rb) / 2;
    if(k <= m) {
        rupd(u, k, 2 * s, lb, m);
    } else {
        rupd(u, k, 2 * s + 1, m + 1, rb);
    }
    rsegt[s].mn = min(rsegt[2 * s + 1].mn, rsegt[2 * s + 1].sm + rsegt[2 * s].mn);
    rsegt[s].sm = rsegt[2 * s].sm + rsegt[2 * s + 1].sm;
}

ll lquery(int l, int r, int s, int lb, int rb) {
    l = max(l, lb), r = min(r, rb);
    if(r < l) return 0;
    if(l == lb && r == rb) {
        return lsegt[s].sm;
    }
    int m = (lb + rb) / 2;
    return lquery(l, r, 2 * s, lb, m) + lquery(l, r, 2 * s + 1, m + 1, rb);
}
ll rquery(int l, int r, int s, int lb, int rb) {
    l = max(l, lb), r = min(r, rb);
    if(r < l) return 0;
    if(l == lb && r == rb) {
        return rsegt[s].sm;
    }
    int m = (lb + rb) / 2;
    return rquery(l, r, 2 * s, lb, m) + rquery(l, r, 2 * s + 1, m + 1, rb);
}

ll lfind(ll v, int l, int& r, int s, int lb, int rb) {
    if(rb < l) return v;
    if(lb == rb && v + lsegt[s].sm < 0) {
        r = lb;
        return v + lsegt[s].sm;
    }
    if(l <= lb && v + lsegt[s].mn >= 0) {
        return v + lsegt[s].sm;
    }
    int m = (lb + rb) / 2;
    v = lfind(v, l, r, 2 * s, lb, m);
    if(r == -1) {
        v = lfind(v, l, r, 2 * s + 1, m + 1, rb);
    }
    return v;
}

ll rfind(ll v, int r, int& l, int s, int lb, int rb) {
    if(r < lb) return v;
    if(lb == rb && v + rsegt[s].sm < 0) {
        l = lb;
        return v + rsegt[s].sm;
    }
    if(rb <= r && v + rsegt[s].mn >= 0) {
        return v + rsegt[s].sm;
    }
    int m = (lb + rb) / 2;
    v = rfind(v, r, l, 2 * s + 1, m + 1, rb);
    if(l == -1) {
        v = rfind(v, r, l, 2 * s, lb, m);
    }
    return v;
}

int N; 
int A[MXN];

void comp(int k, int u) {
    int l = k, r = k;
    if((l == 1 || (A[l - 1] > A[l])) && (r == N || (A[r + 1] > A[r]))) {
        // cout << l << " " << r << " " << u << endl;
        upd(u, l, r, 1, 1, N);
    }
    while(1 < l || r < N) {
        if(l == 1 || (r != N && A[r + 1] < A[l - 1])) {
            int nr = -1;
            lfind(lquery(l, r, 1, 1, N) - A[l], r + 1, nr, 1, 1, N);
            r = nr;
        } else {
            int nl = -1;
            rfind(rquery(l, r, 1, 1, N) - A[r], l - 1, nl, 1, 1, N);
            l = nl;
        }
        if(rquery(l, r, 1, 1, N) - A[r] < 0 && lquery(l, r, 1, 1, N) - A[l] < 0) {
            // cout << l << " " << r << " " << u << endl;
            upd(u, l, r, 1, 1, N);
        }
    }
    r = k;
    while(true) {
        int nr = -1;
        lfind(lquery(k + 1, r, 1, 1, N) - A[k + 1], r + 1, nr, 1, 1, N);
        r = nr;
        if(rquery(k + 1, r, 1, 1, N) - A[r] >= 0) break;
        upd(u, k + 1, r, 1, 1, N);
        if(r >= N) break;
    }
    l = k;
    while(true) {
        int nl = -1;
        rfind(rquery(l, k - 1, 1, 1, N) - A[k - 1], l - 1, nl, 1, 1, N);
        l = nl;
        if(lquery(l, k - 1, 1, 1, N) - A[l] >= 0) break;
        upd(u, l, k - 1, 1, 1, N);
        if(l <= 1) break;
    }
}

int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cin >> N;
    for(int i = 1; i <= N; i++) cin >> A[i];
    for(int i = 1; i < N; i++) {
        lupd(2 * A[i] - A[i + 1], i, 1, 1, N);
    }
    lupd(-INF, N, 1, 1, N);
    for(int i = N; i >= 2; i--) {
        rupd(2 * A[i] - A[i - 1], i, 1, 1, N);
    }
    rupd(-INF, 1, 1, 1, N);
    for(int i = 1; i <= N; i++) {
        int r = i - 1;
        while(true) {
            int nr = -1;
            lfind(lquery(i, r, 1, 1, N) - A[i], r + 1, nr, 1, 1, N);
            r = nr;
            if(rquery(i, r, 1, 1, N) - A[r] >= 0) break;
            upd(1, i, r, 1, 1, N);
            if(r >= N) break;
        }
    }
    build(1, 1, N);
    int Q; cin >> Q;
    for(int i = 0; i < Q; i++) {
        int t; cin >> t;
        if(t == 1) {
            int x, y; cin >> x >> y;
            comp(x, -1);
            int del = y - A[x];
            A[x] = y;
            if(x < N) lupd(2 * del, x, 1, 1, N);
            if(x > 1) rupd(2 * del, x, 1, 1, N);
            if(x > 1) lupd(-del, x - 1, 1, 1, N);
            if(x < N) rupd(-del, x + 1, 1, 1, N);
            comp(x, 1);
        } else {
            int L, R; cin >> L >> R;
            int r = L - 1;
            while(true) {
                int nr = -1;
                lfind(lquery(L, r, 1, 1, N) - A[L], r + 1, nr, 1, 1, N);
                if(nr >= R) break;
                r = nr;
            }
            r++;
            int l = R + 1;
            while(true) {
                int nl = -1;
                rfind(rquery(l, R, 1, 1, N) - A[R], l - 1, nl, 1, 1, N);
                if(nl <= L) break;
                l = nl;
            }
            l--;
            // cout << r << " " << l << endl;
            cout << query(r, l, 1, 0, 1, N).second << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...