洛谷 P1253 扶苏的问题

题意

区间设置某值 , 区间加 , 区间查询最值

思路

对应设置两个懒标记 , 抹平与添加

如果当前被抹平过 , 那么 \(add\) 时只要加抹平后值即可

如果没有抹平过 , \(add\) 正常加

不管有没有添加过 , 抹平时一律归零

需要注意在push_down时 , 在未抹平情况下 , 仍然需要对左右子树的抹平情况判断 , 从而确定添加到哪

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
const int N = 1e6+10;
int a[N];
struct Node {
    int l,r,val,add;
    bool f;
};
Node tr[N<<2];
inline void push_up(int p) {
    tr[p].val = max(tr[p*2].val,tr[p*2+1].val);
    return ;
}
void build(int p,int l,int r) {
    tr[p] = {l,r,a[l],0,false};
    if (l==r) {
        return ;
    }
    int mid = (l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    push_up(p);
}
void push_down(int p) {
    if (tr[p].f) {
        tr[p*2].f = true;
        tr[p*2+1].f = true;
        tr[p].f = false;
        tr[p*2].val = tr[p].val;
        tr[p*2+1].val = tr[p].val;
        tr[p*2].add = 0;
        tr[p*2+1].add = 0;
    }
    else {
        if (!tr[p*2].f) {
            tr[p*2].add += tr[p].add;
        }
        tr[p*2].val += tr[p].add;

        if (!tr[p*2+1].f) {
            tr[p*2+1].add += tr[p].add;
        }
        tr[p*2+1].val += tr[p].add;
        tr[p].add = 0;
    }
}
void add(int p,int l,int r,int k) {
    if (tr[p].r <= r && tr[p].l >= l) {
        tr[p].val += k;
        if (!tr[p].f)
            tr[p].add += k;
        return ;
    }
    push_down(p);
    int mid = tr[p].l + tr[p].r >> 1;
    if (l <= mid)
        add(p*2,l,r,k);
    if (r > mid)
        add(p*2+1,l, r, k);
    push_up(p);
}
void moping(int p,int l,int r,int k) {
    if (tr[p].l >= l && tr[p].r <= r) {
        tr[p].val = k;
        tr[p].f = true;
        tr[p].add = 0;
        return ;
    }
    push_down(p);
    int mid = tr[p].l + tr[p].r >> 1;
    if (l <= mid)
        moping(p*2,l,r,k);
    if (r > mid)
        moping(p*2+1,l, r, k);
    push_up(p);
}
int query(int p,int l,int r) {
    if (tr[p].l>=l && tr[p].r <= r)
        return tr[p].val;
    push_down(p);
    int mid = tr[p].l + tr[p].r >> 1;
    int ans = -1e18-5;
    if (l <= mid)
        ans = max(ans, query(p*2,l,r));
    if (r > mid)
        ans = max(ans, query(p*2+1,l,r));
    return ans;
}
signed main() {
    int n =read(),m=read();
    for (int i = 1; i<= n; i++) {
        a[i]= read();
    }
    build(1,1,n);
    int op,x,y,k;
    while (m--) {
        op =read();
        if (op==1) {
            x = read(), y =read(),k = read();
            moping(1,x,y,k);
        }
        else if (op == 2) {
            x =read(),y=read(),k=read();
            add(1,x,y,k);
        }
        else {
            x=  read(),y =read();
            cout<<query(1,x,y)<<"\n";
        }
    }
    return 0;
}
posted @ 2025-04-02 13:01  Guaninf  阅读(13)  评论(0)    收藏  举报