제출 #1218379

#제출 시각아이디문제언어결과실행 시간메모리
1218379tapilyocaProgression (NOI20_progression)C++20
57 / 100
737 ms69808 KiB
/***********************************************
* auth: tapilyoca                              *
* date: 06/15/2025 at 11:59:22                 *
* dots: https://github.com/tapilyoca/dotilyoca * 
***********************************************/

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9+7;

template<typename T>
using vec = vector<T>;
using ll = long long;
using vll = vec<ll>;
using vvll = vec<vll>;
using pll = pair<ll,ll>;
using str = string;
#define pb push_back
#define dbg(x) if(1) cerr << #x << ": " << x << endl;

/***********************************************/

struct Data {
    ll l, r, pref, suff, mid;
    ll leftval, rightval;

    Data() : l(0), r(0), pref(0), suff(0), mid(0), leftval(0), rightval(0) {}

    Data(ll left, ll right) {
        l = left, r = right;
        pref = suff = mid = 1;
        leftval = rightval = -1e9; // jusjt set this on creation
    }

    void print() {
        cerr << "DATA FROM " << l << " TO " << r << ", PSM: " << pref << ", " << suff << ", " << mid << endl;
    }
};

const Data ident(-1e9, -1e9);

inline Data mergeData(const Data &a, const Data &b) {
    if(a.l == -1e9) return b;
    if(b.l == -1e9) return a;

    Data out(a.l, b.r);
    
    out.pref = a.pref;
    out.leftval = a.leftval;
    out.suff = b.suff;
    out.rightval = b.rightval;
    out.mid = max(a.mid, b.mid);

    // check: prefix extends to whole?
    if(a.pref == (a.r - a.l + 1) and a.leftval == b.leftval) out.pref = a.pref + b.pref;
    if(b.suff == (b.r - b.l + 1) and b.rightval == a.rightval) out.suff = b.suff + a.suff;
    
    // check: mid overlap?
    if(a.rightval == b.leftval) out.mid = max(out.mid, a.suff + b.pref);

    return out;
}

struct Segtree {
    Segtree *lt, *rt;
    Data val;
    ll lazy_add;
    ll lazy_set;
    ll sum = 0;

    void combine() {
        val = mergeData(lt->val,rt->val);
        sum = lt->sum + rt->sum;
    }

    Segtree(ll left, ll right, vec<int> &a) : val(left,right) {
        if(left > right) {
            val = ident;
            lt = rt = nullptr;
            lazy_add = 0;
            lazy_set = -1e18;
            sum = 0;
            return;
        }

        val.l = left;
        val.r = right;
        lt = rt = nullptr;
        lazy_add = 0;
        lazy_set = -1e18;

        if(val.l == val.r) {
            val.leftval = val.rightval = sum = a[val.l];
            return;
        }
        ll m = (val.l+val.r)>>1;
        lt = new Segtree(val.l,m,a);
        rt = new Segtree(m+1,val.r,a);
        combine();
    }

    void propagate() {
        if(lazy_set != -1e18) {
            val.leftval = val.rightval = lazy_set;
            val.pref = val.suff = val.mid = val.r - val.l + 1;
            if(lt) { 
                lt->lazy_set = rt->lazy_set = lazy_set;
                lt->lazy_add = rt->lazy_add = 0;
            }
            lazy_set = -1e18;
        }

        if(lazy_add != 0) {
            val.leftval += lazy_add;
            val.rightval += lazy_add;
            if(lt) {
                lt->lazy_add += lazy_add;
                rt->lazy_add += lazy_add;
            }
            lazy_add = 0;
        }
    }

    Data query(ll ql, ll qr) {
        propagate();
        if(val.r < ql or qr < val.l) return ident;
        if(ql <= val.l and val.r <= qr) return val;
        return mergeData(lt->query(ql,qr), rt->query(ql,qr));
    }

    ll query_sum(ll ql, ll qr) {
        propagate();
        if(val.r < ql or qr < val.l) return 0ll;
        if(ql <= val.l and val.r <= qr) return sum;
        return lt->query_sum(ql,qr) + rt->query_sum(ql,qr);
    }

    void update_add(ll ul, ll ur, ll add) {
        propagate();
        if(val.r < ul or ur < val.l) return;
        if(ul <= val.l and val.r <= ur) {
            lazy_add += add;
            propagate();
            return;
        }
        lt->update_add(ul,ur,add);
        rt->update_add(ul,ur,add);
        combine();
    }

    void update_set(ll ul, ll ur, ll to_set) {
        propagate();
        if(val.r < ul or ur < val.l) return;
        if(ul <= val.l and val.r <= ur) {
            lazy_set = to_set;
            lazy_add = 0;
            propagate();
            return;
        }
        lt->update_set(ul,ur,to_set);
        rt->update_set(ul,ur,to_set);
        combine();
    }

    void preorder() {
        val.print();
        if(lt) {
            lt->preorder();
            rt->preorder();
        }
    }
};

void solve() {
    int n, q;
    cin >> n >> q;
    vec<int> a(n,0);
    vec<int> diff(n-1,0);

    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }

    ll firstElement = a[0];

    for(int i = 1; i < n; i++) {
        diff[i-1] = a[i] - a[i-1];
    }

    // cerr << "DIFF AT START: " << endl;
    // for(auto &x : diff) cerr << x << " ";
    // cerr << endl;

    Segtree st = Segtree(0,n-2,diff);
    
    // st.preorder();

    while(q--) {
        int type;
        cin >> type;
        if(type == 1) {
            ll l, r, s, c;
            cin >> l >> r >> s >> c;

            if(l == 1) firstElement -= s;

            l -= 2;
            r -= 2;
            ll totAdded = (r-l) * c + s;


            // cerr << "Segtree terms: update on " << l << " " << r << endl;
            st.update_add(l,l,s);
            if(l != r) st.update_add(l+1,r,c);
            if(r != n-2) {
                // cerr << "fix diff array, add " << -totAdded << " to " << r+1 << endl;
                st.update_add(r+1,r+1,-totAdded);
            }

            // DEBUG PRINT ARRAY
            // cerr << "DIFF AFTER UPDATE: " << endl;
            // for(int i = 0; i < n-1; i++) cerr << st.query(i,i).leftval << " ";
            // cerr << endl;
        }

        else if(type == 2) {
            ll l, r, s, c;
            cin >> l >> r >> s >> c;

            ll old_first_element = firstElement;
            ll old_prev_element = (l == 1 ? -1e18 : (l == 2 ? old_first_element : old_first_element + st.query_sum(0,l-3)));
            ll old_next_element = (r == n ? -1e18 : old_first_element + st.query_sum(0,r-2));
            ll finalSet = (r-l) * c + s;

            if(l == 1) firstElement = s; // more cases

            l -= 2;
            r -= 2;

            // cerr << "On diff: letting " << l << " " << l << " become " << s - old_prev_element << endl;
            st.update_set(l,l,s - old_prev_element);
            if(l != r) st.update_set(l+1,r,c);
            if(r != n-2) {
                st.update_set(r+1, r+1, old_next_element - finalSet);
            }

            // cerr << "DIFF AFTER UPDATE: " << endl;
            // for(int i = 0; i < n-1; i++) cerr << st.query(i,i).leftval << " ";
            // cerr << endl;
        }

        else if(type == 3) {
            // query
            ll l,r;
            cin >> l >> r;
            if(l == r) {
                cout << 1 << endl;
                continue;
            }
            l--;
            r -= 2;

            Data yay = st.query(l,r);
            cout << max({yay.pref,yay.suff,yay.mid}) + 1 << endl;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int t = 1;

    while(t--) {
        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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...