BZOJ 3064 Tyvj 1518 CPU监控 线段树维护历史最大值

题目大意:给出一个数列要求支持:查询区间最大值,查询区间历史最大值,区间加,区间修改

除了历史最值都是最裸的线段树…
如果上最裸的线段树维护这个东西,在标记下推的时候可能把最值直接推没了…
看看怎么维护这个最值

在每个线段树结点上多维护两个量:历史最大的加法标记,历史最大的修改标记
更新子结点的历史最大值:当前结点的历史加法;当前结点历史修改;子结点的当前最大值
更新子结点的历史加法:当前结点的历史加法;子结点的当前加法
更新子结点的历史修改:当前结点的当前覆盖;子结点的历史覆盖
其他的都正常更新就行…

0表示现在,1表示历史

#include <cstdio>
#include <algorithm>
#define N 100005
#define INF (1ll<<60)
using namespace std;
typedef long long LL;
struct Node {
    Node* ch[2];
    int l,r;
    LL maxx[2],add_mark[2],change_mark[2];
    Node() {}
    Node(int _l,int _r):l(_l),r(_r) {
        maxx[0]=maxx[1]=0;
        add_mark[0]=add_mark[1]=0;
        change_mark[0]=change_mark[1]=-INF;
    }
    void* operator new(size_t) {
        static Node *C,*mempool;
        if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20);
        return C++;
    }
    void add(int v) {
        maxx[0]+=v;
        if(change_mark[0]!=-INF) change_mark[0]+=v;
        else add_mark[0]+=v;
        add_mark[1]=max(add_mark[1],add_mark[0]);
        maxx[1]=max(maxx[1],maxx[0]);
        return ;
    }
    void change(int v) {
        change_mark[0]=maxx[0]=v;
        add_mark[0]=0;
        change_mark[1]=max(change_mark[1],change_mark[0]);
        maxx[1]=max(maxx[1],maxx[0]);
        return ;
    }
    void pushdown() {
        for(int i=0;i<2;++i) {
            ch[i]->maxx[1]=max(ch[i]->maxx[1],max(change_mark[1],ch[i]->maxx[0]+add_mark[1]));
            if(ch[i]->change_mark[0]==-INF) ch[i]->add_mark[1]=max(ch[i]->add_mark[1],ch[i]->add_mark[0]+add_mark[1]);
            else ch[i]->change_mark[1]=max(ch[i]->change_mark[1],ch[i]->change_mark[0]+add_mark[1]);
            if(add_mark[0]) ch[i]->add(add_mark[0]);
            if(change_mark[0]!=-INF) ch[i]->change(change_mark[0]);
            ch[i]->change_mark[1]=max(ch[i]->change_mark[1],change_mark[1]);
        }
        add_mark[0]=add_mark[1]=0;
        change_mark[0]=change_mark[1]=-INF;
        return ;
    }
    void maintain() {
        maxx[0]=max(ch[0]->maxx[0],ch[1]->maxx[0]);
        maxx[1]=max(ch[0]->maxx[1],ch[1]->maxx[1]);
        return ;
    }
}*root;
int n,m,a[N];
void init(Node*& o,int l,int r) {
    o=new Node(l,r);
    if(l==r) {
        o->maxx[0]=o->maxx[1]=a[l];
        return ;
    }
    int mid=l+r>>1;
    init(o->ch[0],l,mid), init(o->ch[1],mid+1,r);
    o->maintain();
    return ;
}
LL Query(Node* o,int l,int r,int mode) {
    if(o->l==l && o->r==r) return o->maxx[mode];
    o->pushdown();
    int mid=o->l+o->r>>1;
    if(r<=mid) return Query(o->ch[0],l,r,mode);
    if(l>mid) return Query(o->ch[1],l,r,mode);
    return max(Query(o->ch[0],l,mid,mode),Query(o->ch[1],mid+1,r,mode));
}
void Modify(Node* o,int l,int r,int v,int mode) {
    if(o->l==l && o->r==r) {
        if(!mode) o->add(v);
        else o->change(v);
        return ;
    }
    o->pushdown();
    int mid=o->l+o->r>>1;
    if(r<=mid) Modify(o->ch[0],l,r,v,mode);
    else if(l>mid) Modify(o->ch[1],l,r,v,mode);
    else Modify(o->ch[0],l,mid,v,mode), Modify(o->ch[1],mid+1,r,v,mode);
    o->maintain();
    return ;
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",a+i);
    init(root,1,n);
    for(scanf("%d",&m);m;m--) {
        char mode[2];
        int x,y,z;
        scanf("%s%d%d",mode,&x,&y);
        if(mode[0]=='Q') printf("%lld\n",Query(root,x,y,0));
        if(mode[0]=='A') printf("%lld\n",Query(root,x,y,1));
        if(mode[0]=='P') scanf("%d",&z), Modify(root,x,y,z,0);
        if(mode[0]=='C') scanf("%d",&z), Modify(root,x,y,z,1);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值