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

$(x,y)$ 表示加完 $x$,再对 $y$ 取 max 的操作.  

那么有 $(a,b)+(c,d)=(a+c,max(b+c,d))$                         

然后对于两个标记取 max 的话是 $(max(a,c),max(b,d))$  

知道这些之后就好做了.  

一定要注意:先更新历史最值标记,然后再更新当前最值(因为历史最值标记需要用到当前最值标记)  

code:   

#include <cstdio> 
#include <algorithm> 
#include <cstring>    
#define N 100006   
#define lson x<<1  
#define rson x<<1|1  
#define inf 0x3f3f3f3f    
#define I(s) freopen(s".in","r",stdin) 
#define O(s) freopen(s".out","w",stdout)   
#define setIO(s) I(s),O(s) 
using namespace std;           
struct data 
{      
    int x,y;  
    data(int a=0,int b=-inf) { x=a,y=b; }         
    data operator+(const data &a)const { return data(max(-inf,x+a.x),max(y+a.x,a.y)); }   
    data operator*(const data &a)const { return data(max(x,a.x),max(y,a.y)); }        
}ptag[N<<2],ntag[N<<2];     
int n;                  
int pmax[N<<2],nmax[N<<2];             
void pushup(int x) 
{
    pmax[x]=max(pmax[lson],pmax[rson]);  
    nmax[x]=max(nmax[lson],nmax[rson]);  
}    
void build(int l,int r,int x) 
{
    ptag[x]=ntag[x]=data();    
    if(l==r) 
    {   
        scanf("%d",&nmax[x]),pmax[x]=nmax[x]; 
        return;   
    } 
    int mid=(l+r)>>1;   
    build(l,mid,lson),build(mid+1,r,rson);   
    pushup(x);  
}   
//  对于历史最大值           
void mark_n(int x,data v) 
{
    ntag[x]=ntag[x]+v;     
    nmax[x]=max(nmax[x]+v.x,v.y);        
}
void mark_p(int x,data v) 
{           
    ptag[x]=ptag[x]*(ntag[x]+v);      
    pmax[x]=max(pmax[x],max(nmax[x]+v.x,v.y));       
}       
void pushdown(int x) 
{ 
    mark_p(lson,ptag[x]); 
    mark_n(lson,ntag[x]);      
    mark_p(rson,ptag[x]);        
    mark_n(rson,ntag[x]);
    ntag[x]=ptag[x]=data();    
}
void update(int l,int r,int x,int L,int R,data v) 
{  
    if(l>=L&&r<=R) 
    {          
        mark_p(x,v); 
        mark_n(x,v);   
        return; 
    }  
    pushdown(x); 
    int mid=(l+r)>>1;     
    if(L<=mid) update(l,mid,lson,L,R,v); 
    if(R>mid)  update(mid+1,r,rson,L,R,v);   
    pushup(x); 
}  
int query(int l,int r,int x,int L,int R,int o) 
{
    if(l>=L&&r<=R) return o?nmax[x]:pmax[x];     
    pushdown(x); 
    int mid=(l+r)>>1,re=-inf;      
    if(L<=mid)  re=max(re,query(l,mid,lson,L,R,o));  
    if(R>mid)   re=max(re,query(mid+1,r,rson,L,R,o)); 
    return re;  
}
int main() 
{ 
    // setIO("input");    
    int m; 
    scanf("%d",&n);         
    build(1,n,1);   
    scanf("%d",&m);   
    for(int i=1;i<=m;++i) 
    {
        char opt[2];   
        int l,r,z; 
        scanf("%s%d%d",opt,&l,&r); 
        if(opt[0]=='Q')  printf("%d
",query(1,n,1,l,r,1)); 
        if(opt[0]=='A')  printf("%d
",query(1,n,1,l,r,0));   
        if(opt[0]=='P')  scanf("%d",&z),update(1,n,1,l,r,data(z,-inf));
        if(opt[0]=='C')  scanf("%d",&z),update(1,n,1,l,r,data(-inf,z));  
    }
    return 0; 
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12561423.html