Submission #730985

#TimeUsernameProblemLanguageResultExecution timeMemory
730985fatemetmhrFish 2 (JOI22_fish2)C++17
100 / 100
840 ms16564 KiB
// ~ Be Name Khoda ~
 
#include <bits/stdc++.h>
//#pragma GCC optimize ("Ofast")
//#pragma GCC target("avx2")
#pragma GCC optimize("unroll-loops,O3")
 
using namespace std;
 
typedef long long ll;
typedef pair <int, int> pii;
 
#define pb       push_back
#define mp       make_pair
#define all(x)   x.begin(), x.end()
#define fi       first
#define se       second
 
const int maxn  =  2e7   + 10;
const int maxn5 =  1e5   + 10;
const int maxnt =  5e5   + 10;
const int maxn3 =  1e3   + 10;
const int mod   =  1e9   +  7;
 
 
int a[maxn5];
int n;
vector <int> av;

namespace fen{

    ll fen[maxn5];

    inline void add(int id, ll val){
        for(++id; id < maxn5; id += id & -id)
            fen[id] += val;
    }

    inline ll get(int id){
        ll ret = 0;
        for(++id; id; id -= id & -id)
            ret += fen[id];
        return ret;
    }

    inline ll get(int l, int r){
        if(r < l || r < 0)
            return 0;
        if(l == r)
            return a[l];
        return get(r) - (l ? get(l - 1) : 0);
    }
}
 
namespace seg{
 
    pii mn[maxnt];
    int lazy[maxnt], mx[maxnt];
 
    inline pii comb(pii a, pii b){
        pii ans = min(a, b);
        if(a.fi == b.fi)
            ans.se = a.se + b.se;
        return ans;
    }
 
    void build(int l, int r, int v){
        mn[v] = {0, r - l};
        if(r - l == 1)
            return;
        int mid = (l + r) >> 1;
        build(l, mid, v * 2);
        build(mid, r, v * 2 + 1);
    }
 
    void upd(int l, int r, int id, int v){
        if(r - l == 1){
            mx[v] = a[id];
            return;
        }
        int mid = (l + r) >> 1;
        if(id < mid)
            upd(l, mid, id, v * 2);
        else
            upd(mid, r, id, v * 2 + 1);
        mx[v] = max(mx[v * 2], mx[v * 2 + 1]);
    }
 
    void add(int l, int r, int lq, int rq, int val, int v){
        if(rq <= l || r <= lq)
            return;
        if(lq <= l && r <= rq){
            lazy[v] += val;
            mn[v].fi += val;
            return;
        }
        int mid = (l + r) >> 1;
        add(l, mid, lq, rq, val, v * 2);
        add(mid, r, lq, rq, val, v * 2 + 1);
        mn[v] = comb(mn[v * 2], mn[v * 2 + 1]);
        mn[v].fi += lazy[v];
    }
 
    pii get_min(int l, int r, int lq, int rq, int v){
        if(rq <= l || r <= lq)
            return {mod, 0};
        if(lq <= l && r <= rq)
            return mn[v];
        int mid = (l + r) >> 1;
        pii ans = comb(get_min(l, mid, lq, rq, v * 2), get_min(mid, r, lq, rq, v * 2 + 1));
        ans.fi += lazy[v];
        return ans;
    }
 
    int get_first(int l, int r, int lq, int rq, ll val, int v){
        if(rq <= l || r <= lq || mx[v] < val)
            return -1;
        if(r - l == 1)
            return l;
        int mid = (l + r) >> 1;
        int ans = get_first(l, mid, lq, rq, val, v * 2);
        if(ans != -1)
            return ans;
        return get_first(mid, r, lq, rq, val, v * 2 + 1);
    }
 
    int get_last(int l, int r, int lq, int rq, ll val, int v){
        if(rq <= l || r <= lq || mx[v] < val)
            return -1;
        if(r - l == 1)
            return l;
        int mid = (l + r) >> 1;
        int ans = get_last(mid, r, lq, rq, val, v * 2 + 1);
        if(ans != -1)
            return ans;
        return get_last(l, mid, lq, rq, val, v * 2);
    }
 
}

struct segment_tree{

    ll lazy[maxnt], mx[maxnt];

    void add(int l, int r, int lq, int rq, ll val, int v){
        if(rq <= l || r <= lq)
            return;
        if(lq <= l && r <= rq){
            lazy[v] += val;
            mx[v] += val;
            return;
        }
        int mid = (l + r) >> 1;
        add(l, mid, lq, rq, val, v * 2);
        add(mid, r, lq, rq, val, v * 2 + 1);
        mx[v] = max(mx[v * 2], mx[v * 2 + 1]) + lazy[v];
    }

    int get_first(int l, int r, int lq, int rq, ll val, int v){
        if(rq <= l || r <= lq || mx[v] < val)
            return -1;
        if(r - l == 1)
            return l;
        int mid = (l + r) >> 1;
        val -= lazy[v];
        int ans = get_first(l, mid, lq, rq, val, v * 2);
        if(ans != -1)
            return ans;
        return get_first(mid, r, lq, rq, val, v * 2 + 1);
    }
 
    int get_last(int l, int r, int lq, int rq, ll val, int v){
        if(rq <= l || r <= lq || mx[v] < val)
            return -1;
        if(r - l == 1)
            return l;
        int mid = (l + r) >> 1;
        val -= lazy[v];
        int ans = get_last(mid, r, lq, rq, val, v * 2 + 1);
        if(ans != -1)
            return ans;
        return get_last(l, mid, lq, rq, val, v * 2);
    }

} segpre, segsuf;

inline void chval(int id, int val){
    fen::add(id, val - a[id]);
    segpre.add(0, n, id + 1, n, a[id] - val, 1);
    segpre.add(0, n, id, id + 1, val - a[id], 1);
    segsuf.add(0, n, 0, id, a[id] - val, 1);
    segsuf.add(0, n, id, id + 1, val - a[id], 1);
    a[id] = val;
    seg::upd(0, n, id, 1);
}
 
 
inline void update(int x, int y){
    //cerr << "ya here " << x << ' ' << y << '\n';
    if(y == a[x])
        return;
    if(y > a[x]){
        ll sum1 = a[x], sum2 = a[x];
        int i1 = seg::get_last(0, n, 0, x, a[x] + 1, 1);
        int i2 = seg::get_first(0, n, x + 1, n, a[x] + 1, 1);
        while(i1 != -1 && i2 != -1){
            ll sum = fen::get(i1 + 1, i2 - 1);
            if(sum < min(a[i1], a[i2]) && sum - a[x] + y >= min(a[i1], a[i2]))
                seg::add(0, n, i1 + 1, i2, -1, 1);
            if(a[i1] <= a[i2]){
                sum1 += a[i1];
                i1 = seg::get_last(0, n, 0, i1, sum1 + 1, 1);
            }
            else{
                sum2 += a[i2];
                i2 = seg::get_first(0, n, i2, n, sum2 + 1, 1);
            }
        }
        ll sum = 0;
        int i = seg::get_first(0, n, x + 1, n, a[x], 1);
        while(i != -1){
            ll have = fen::get(x + 1, i - 1);
            if(have >= min(a[x], a[i]) && have < min(y, a[i]))
                seg::add(0, n, x + 1, i, 1, 1);
            sum += a[i];
            i = seg::get_first(0, n, i + 1, n, sum + 1, 1);
        }
        sum = 0;
        i = seg::get_last(0, n, 0, x, a[x], 1);
        while(i != -1){
            ll have = fen::get(i + 1, x - 1);
            if(have >= min(a[x], a[i]) && have < min(y, a[i]))
                seg::add(0, n, i + 1, x, 1, 1);
            sum += a[i];
            i = seg::get_last(0, n, 0, i, sum + 1, 1);
        }
        chval(x, y);
        return;
    }

    ll sum1 = y, sum2 = y;
    int i1 = seg::get_last(0, n, 0, x, y + 1, 1);
    int i2 = seg::get_first(0, n, x + 1, n, y + 1, 1);
    while(i1 != -1 && i2 != -1){
        ll sum = fen::get(i1 + 1, i2 - 1);
        if(sum >= min(a[i1], a[i2]) && sum - a[x] + y < min(a[i1], a[i2]))
            seg::add(0, n, i1 + 1, i2, 1, 1);
        if(a[i1] <= a[i2]){
            sum1 += a[i1];
            i1 = seg::get_last(0, n, 0, i1, sum1 + 1, 1);
        }
        else{
            sum2 += a[i2];
            i2 = seg::get_first(0, n, i2, n, sum2 + 1, 1);
        }
    }
    ll sum = 0;
    int i = x + 1;
    while(i != -1){
        ll have = fen::get(x + 1, i - 1);
        if(have < min(a[x], a[i]) && have >= min(y, a[i]))
            seg::add(0, n, x + 1, i, -1, 1);
        sum += a[i];
        i = seg::get_first(0, n, i + 1, n, sum + 1, 1);
    }
    sum = 0;
    i = x - 1;
    while(i != -1){
        ll have = fen::get(i + 1, x - 1);
        if(have < min(a[x], a[i]) && have >= min(y, a[i]))
            seg::add(0, n, i + 1, x, -1, 1);
        sum += a[i];
        i = seg::get_last(0, n, 0, i, sum + 1, 1);
    }
    chval(x, y);
    return;
}

inline void add(int l, int r){
    ll sum = fen::get(l + 1, r - 1);
    if(sum >= min(a[l], a[r]))
        return;
    seg::add(0, n, l + 1, r, 1, 1);
}
 
int main()
{
    ios_base::sync_with_stdio(false); cin.tie(0);
 
    cin >> n;
    seg::build(0, n, 1);
    for(int i = 0; i < n; i++){
        int keep;
        cin >> keep;
        chval(i, keep);
        while(av.size() && a[av.back()] <= a[i]){
            add(av.back(), i);
            av.pop_back();
        }
        if(av.size())
            add(av.back(), i);
        av.pb(i);
    }
 
    int q; cin >> q;
    while(q--){
        int ty, x, y; cin >> ty >> x >> y;
        x--;
        if(ty == 1)
            update(x, y);
        else{
            y--;
            ll sumpre = fen::get(0, x - 1);
            int l = segpre.get_last(0, n, x, y + 1, (-sumpre) + 1, 1);
            if(l == -1)
                l = x;
            sumpre = fen::get(y + 1, n);
            int r = segsuf.get_first(0, n, x, y + 1, (-sumpre) + 1, 1);
            if(r == -1)
                r = y;
            cout << seg::get_min(0, n, l, r + 1, 1).se << '\n';
        }
    }
}
 
/*
5
6 4 2 2 6
3
1 3 1
2 2 5
2 1 5
2 2 4
 
5
6 4 2 2 6
1
2 1 3
2 1 5
1 3 1
2 2 5
2 1 5
2 2 4
 
3
6 4 2
1
2 1 2
 
10
2 3 5 10 1 3 4 9 5 2
2
1 4 1000000000
2 1 10
1 8 20
1 4 8
2 1 10 

7
27 18 36 31 55 86 4 
4
1 7 18
1 7 60
1 3 11
2 1 6

7
27 18 36 31 55 86 60
3
2 2 3
1 3 11
2 1 6

8
41 53 10 12 43 91 11 92 
10
2 5 8
1 8 65
2 4 7
2 3 8
1 2 37
1 8 5
2 7 8
1 8 43
1 1 30
1 6 60
*/
#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...