40,求调

P1253 扶苏的问题

Exile_Code @ 2024-01-01 23:56:15

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <list>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <unordered_set>
#include <math.h>
#include <functional>
#include<unordered_map>

#define ull             unsigned long long 
#define ll              long long
#define pii             pair<ll,ll>
#define ft              first
#define sd              second
#define cy              cout<<"YES"<<endl
#define cn              cout<<"NO"<<endl
#define forn(i,n)       for(ll (i)=0;(i)<(n);(i)++)   
#define forne(i,n)      for(ll (i)=1;(i)<=(n);(i)++)
#define rforn(i,n)      for(ll (i)=(n-1);i>=0;i--)
#define rforne(i,n)     for(ll (i)=n;i>=1;i--)
#define vv              vector
#define inf             1e9
const int N = 4e5 + 100;
const int mod = 1e9 + 7;
ll T;

class Segment_tree {
    /*
    叶子节点储存元素本身,非叶子节点存储统计值,用来维护区间和,区间最值,区间GCD
    父节点的编号是p,左孩子的编号是2p,右孩子的编号是2p+1
    */
    struct node {
        ll l, r, add,mx,upd;
    };
    vv<node>tr;
    vv<ll>w;
#define lc p<<1
#define rc (p<<1)|1
//p<<2一定是一个偶数,偶数的末位是0,所以按位或1,相当于+1
#define LEN(x) (tr[(x)].r - tr[(x)].l + 1)  //区间长度包括端点
#define MID(x) (tr[(x)].l + tr[(x)].r) >> 1 //中间点
#define trpl tr[p].l
#define trpr tr[p].r
#define trps tr[p].sum
#define trpd tr[p].add
public:
    void init(int n) {
        tr = vv<node>(4 * n + 3);
        w = vv<ll>(n + 1);
        forne(i, n)
            cin >> w[i];
        build(1, 1, n);
    }
    void pushup(int p) {
        //trps = tr[lc].sum + tr[rc].sum;
        tr[p].mx = max(tr[lc].mx, tr[rc].mx);
    }
    void build(int p, int l, int r) {
        tr[p] = { l,r,0,w[l],0 };
        if (l == r)     return;
        int m = MID(p);
        build(lc, l, m); build(rc, m + 1, r);
        pushup(p);
    }
    ll query(int p, int l, int r) {
        ll mx = -1e9-100;   
        if (l <= trpl && trpr <= r)
            return tr[p].mx;
        int m = MID(p); pushdown(p);
        if (l <= m) mx=max(mx,query(lc, l, r));
        if (r > m)  mx=max(mx,query(rc, l, r));
        return mx;
    }
    void pushdown(int p) {
        if (tr[p].upd) {
            tr[p].mx = tr[p].upd;
            tr[lc].upd = tr[p].upd;
            tr[rc].upd = tr[p].upd;
            tr[lc].add =0;
            tr[rc].add =0;
            tr[p].upd = 0;
        }
        if (tr[p].add) {
            tr[lc].mx += tr[p].add;
            tr[rc].mx += tr[p].add;
            tr[lc].add += trpd;
            tr[rc].add += trpd;
            tr[p].add = 0;
        }
    }
    //区间查询,拆分拼凑
    //如果查询区间完全覆盖掉当前的节点区间,就立刻返回当前的区间值 On
    void update(int p, int l, int r, int k) {
        if (l <= trpl && trpr <= r) {
            if (tr[p].upd != 0)
                tr[p].upd += k;
            else
                trpd += k;
            tr[p].mx += k;
            return;
        }
        int m = MID(p);
        pushdown(p);
        if (l <= m) update(lc, l, r, k);
        if (r > m)  update(rc, l, r, k);
        pushup(p);
    }
    void update_all(int p, int l, int r, int x) {
        if (l <= trpl && trpr <= r) {
            tr[p].upd = x;
            tr[p].add = 0;
            tr[p].mx = x;
            return;
        }
        int m = MID(p);
        pushdown(p);
        if (l <= m) update_all(lc, l, r, x);
        if (r > m)  update_all(rc, l, r, x);
        pushup(p);
    }
};
void solve() {

    //1 1 4 5 1 4
    //6 6 4 5 1 4
    //6 6 6 7 1 4
    //

    int n, q;
    cin >> n >> q;
    Segment_tree fuction;
    fuction.init(n);
    while (q--) {
        int ch; cin >> ch;
        if (ch == 1) {
            int l, r, x; cin >> l >> r >> x;
            fuction.update_all(1, l, r, x);
        }
        else if(ch==2) {
            int l, r, x; cin >> l >> r >> x;
            fuction.update(1,l, r, x);
        }
        else {
            int l, r; cin >> l >> r;
            cout << fuction.query(1, l, r) << endl;
        }

    }

}
int main() {

    T = 1;
    //cin >> T;
    while (T--)
        solve();
}

by 杜都督 @ 2024-01-30 06:03:04

修改的地方我基本上都用@@@标注了,如果漏标请自行消化(最近太累了检查不动了)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <list>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <unordered_set>
#include <math.h>
#include <functional>
#include<unordered_map>

#define ull             unsigned long long 
#define ll              long long
#define pii             pair<ll,ll>
#define ft              first
#define sd              second
#define cy              cout<<"YES"<<endl
#define cn              cout<<"NO"<<endl
#define forn(i,n)       for(ll (i)=0;(i)<(n);(i)++)   
#define forne(i,n)      for(ll (i)=1;(i)<=(n);(i)++)
#define rforn(i,n)      for(ll (i)=(n-1);i>=0;i--)
#define rforne(i,n)     for(ll (i)=n;i>=1;i--)
#define vv              vector
#define inf (0x3f3f3f3f3f3f3f3f)    // @@@inf也应该是ll级别的,1e9是不够的(至少对于query()来说)
const int N = 4e5 + 100;
const int mod = 1e9 + 7;
ll T;

class Segment_tree {
    /*
    叶子节点储存元素本身,非叶子节点存储统计值,用来维护区间和,区间最值,区间GCD
    父节点的编号是p,左孩子的编号是2p,右孩子的编号是2p+1
    */
    struct node {
        ll l, r, add,mx,upd;
    };
    vv<node>tr;
    vv<ll>w;
#define lc p<<1
#define rc (p<<1)|1
//p<<2一定是一个偶数,偶数的末位是0,所以按位或1,相当于+1
#define LEN(x) (tr[(x)].r - tr[(x)].l + 1)  //区间长度包括端点
#define MID(x) (tr[(x)].l + tr[(x)].r) >> 1 //中间点
#define trpl tr[p].l
#define trpr tr[p].r
#define trps tr[p].sum
#define trpd tr[p].add

public:
    void init(int n) {
        tr = vv<node>(4 * n + 3);
        w = vv<ll>(n + 1);
        forne(i, n)
            cin >> w[i];
        build(1, 1, n);
    }
    void pushup(int p) {
        //trps = tr[lc].sum + tr[rc].sum;
        tr[p].mx = max(tr[lc].mx, tr[rc].mx);
    }
    void build(int p, int l, int r) {
        tr[p] = { l,r,0,w[l],inf };    // @@@upd操作存在x == 0的情况,所以直接用tr[p].upd是否为0来标识是否进行upd操作是狭隘的,可以考虑将inf视为不进行upd,而一切<inf的(包括0和负数)都视为进行upd
        if (l == r)     return;
        int m = MID(p);
        build(lc, l, m); build(rc, m + 1, r);
        pushup(p);
    }
    ll query(int p, int l, int r) {
        ll mx = -inf;    // @@@
        if (l <= trpl && trpr <= r)
            return tr[p].mx;
        int m = MID(p); pushdown(p);
        if (l <= m) mx=max(mx,query(lc, l, r));
        if (r > m)  mx=max(mx,query(rc, l, r));
        return mx;
    }
    void pushdown(int p) {
        if (tr[p].upd < inf) {    // @@@
            // tr[p].mx = tr[p].upd;    @@@你原来那么写也行
            tr[lc].mx = tr[p].upd;    // @@@
            tr[rc].mx = tr[p].upd;    // @@@
            tr[lc].upd = tr[p].upd;
            tr[rc].upd = tr[p].upd;
            tr[lc].add =0;
            tr[rc].add =0;
            tr[p].upd = inf;    // @@@
        }
        if (tr[p].add) {
            tr[lc].mx += tr[p].add;
            tr[rc].mx += tr[p].add;
            if (tr[lc].upd < inf) tr[lc].upd += tr[p].add;    // @@@重要逻辑,如果upd标记已存在,则直接将upd加上add即可,无需修改add标记,否则才修改add标记
            else tr[lc].add += trpd;    // @@@
            if (tr[rc].upd < inf) tr[rc].upd += tr[p].add;    // @@@
            else tr[rc].add += trpd;    // @@@
            tr[p].add = 0;
        }
    }
    //区间查询,拆分拼凑
    //如果查询区间完全覆盖掉当前的节点区间,就立刻返回当前的区间值 On
    void update(int p, int l, int r, int k) {
        if (l <= trpl && trpr <= r) {
            if (tr[p].upd < inf)    // @@@
                tr[p].upd += k;
            else
                trpd += k;
            tr[p].mx += k;
            return;
        }
        int m = MID(p);
        pushdown(p);
        if (l <= m) update(lc, l, r, k);
        if (r > m)  update(rc, l, r, k);
        pushup(p);
    }
    void update_all(int p, int l, int r, int x) {
        if (l <= trpl && trpr <= r) {
            tr[p].upd = x;
            tr[p].add = 0;
            tr[p].mx = x;
            return;
        }
        int m = MID(p);
        pushdown(p);
        if (l <= m) update_all(lc, l, r, x);
        if (r > m)  update_all(rc, l, r, x);
        pushup(p);
    }
};
void solve() {
    // @@@不这么做会导致#10TLE
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    //1 1 4 5 1 4
    //6 6 4 5 1 4
    //6 6 6 7 1 4
    //

    int n, q;
    cin >> n >> q;
    Segment_tree fuction;
    fuction.init(n);
    while (q--) {
        int ch; cin >> ch;
        if (ch == 1) {
            int l, r, x; cin >> l >> r >> x;
            fuction.update_all(1, l, r, x);
        }
        else if(ch==2) {
            int l, r, x; cin >> l >> r >> x;
            fuction.update(1,l, r, x);
        }
        else {
            int l, r; cin >> l >> r;
            cout << fuction.query(1, l, r) << endl;
        }

    }

}
int main() {

    T = 1;
    //cin >> T;
    while (T--)
        solve();
}

|