UOJ164 V 线段树lazytag维护历史最值

题意:维护一列数,支持:
1.区间加A
2.区间减A,减法结束后每个位置与0取max
3.区间覆盖成A
4.询问单点当前值
5.询问单点历史最值

线段树lazytag维护历史最值,要记录四个数组,注意转移以及初始条件。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=10000010;
const LL INF=1e18;
int n,m;
struct Tree{
    LL add,addmax,r,rmax;
}tree[maxn<<2],tmp;
int qx;
int ql,qr;
int type;
LL s[maxn];
void build(int o,int l,int r){
    if(l==r){
        tree[o]=(Tree){0,0,-INF,-INF};
        return;
    }
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
}
Tree update(Tree u,Tree v){
    return (Tree){
        max(u.add+v.add,-INF),max(u.addmax,u.add+v.addmax),max(u.r+v.add,v.r),max(max(u.rmax,v.rmax),u.r+v.addmax)
    };
}
void pushdown(int o){
    tree[o<<1]=update(tree[o<<1],tree[o]);
    tree[o<<1|1]=update(tree[o<<1|1],tree[o]);
    tree[o]=(Tree){0,-INF,0,-INF};
}
void change(int o,int l,int r){
    if(ql<=l && qr>=r){
        tree[o]=update(tree[o],tmp);
        return;
    }
    pushdown(o);
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    if(ql<=mid) change(lc,l,mid);
    if(qr>mid) change(rc,mid+1,r);
}
void query(int o,int l,int r){
    if(l==r){
        if(type==4) printf("%lld\n",max(tree[o].add+s[qx],tree[o].r));
        if(type==5) printf("%lld\n",max(tree[o].addmax+s[qx],tree[o].rmax));
        return;
    }
    pushdown(o);
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    if(qx<=mid) query(lc,l,mid);
    else query(rc,mid+1,r);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&s[i]);
    build(1,1,n);
    while(m--){
        scanf("%d",&type);
        int x;
        if(type<=3){
            scanf("%d%d",&ql,&qr);
            scanf("%d",&x);
            if(type==1)tmp=(Tree){x,x,-INF,-INF};
            if(type==2)tmp=(Tree){-x,-x,0,0};
            if(type==3)tmp=(Tree){-INF,-INF,x,x};
            change(1,1,n);
        }else{
            scanf("%d",&qx);
            query(1,1,n);
        }
    }
    return 0;
}

^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值