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

来源:互联网 发布:程序员鼓励师王牧牧 编辑:程序博客网 时间:2024/06/05 08:49

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

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

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

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;}
原创粉丝点击