BZOJ 4695: 最假女选手 segment-tree-beats

新学 segment-tree-beats.   

这道题在区间取 min/max 的基础上还有一个区间加,那么显然要先做区间加,再取 min/max. 

code:    

// bzoj 最假女选手   
#include <cstdio> 
#include <algorithm>  
#include <cstring>             
#define N 500007 
#define ll long long  
#define lson x<<1 
#define rson x<<1|1          
using namespace std;  
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
    int x=0,f=1; char s=nc();
    while(s<'0'||s>'9') {if(s=='-')f=-1;s=nc();}
    while(s>='0'&&s<='9') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    return x*f;
}     
const int inf=1<<30;     
int n;   
ll sum[N<<2];    
int sn[N<<2],sm[N<<2],mn[N<<2],mx[N<<2],mi[N<<2],ma[N<<2],add[N<<2],len[N<<2]; 
void pushup(int x) 
{  
    sum[x]=sum[lson]+sum[rson];       
    if(mn[lson]<mn[rson])  
        mn[x]=mn[lson],mi[x]=mi[lson],sn[x]=min(sn[lson],mn[rson]);    
    if(mn[rson]<mn[lson]) 
        mn[x]=mn[rson],mi[x]=mi[rson],sn[x]=min(sn[rson],mn[lson]);  
    if(mn[lson]==mn[rson]) 
        mn[x]=mn[lson],mi[x]=mi[lson]+mi[rson],sn[x]=min(sn[lson],sn[rson]);   
    if(mx[lson]>mx[rson]) 
        mx[x]=mx[lson],ma[x]=ma[lson],sm[x]=max(sm[lson],mx[rson]);  
    if(mx[rson]>mx[lson]) 
        mx[x]=mx[rson],ma[x]=ma[rson],sm[x]=max(sm[rson],mx[lson]);   
    if(mx[lson]==mx[rson]) 
        mx[x]=mx[lson],ma[x]=ma[lson]+ma[rson],sm[x]=max(sm[lson],sm[rson]);     
}    
void mark_add(int x,int v) 
{    
    mn[x]+=v,mx[x]+=v,sn[x]+=v,sm[x]+=v,add[x]+=v;   
    sum[x]+=(ll)len[x]*v;   
}   
void mark_max(int x,int v) 
{   
    if(mx[x]>v) 
    {     
        sum[x]-=(ll)ma[x]*(mx[x]-v);      
        if(mn[x]==mx[x])  mn[x]=v;   
        if(sn[x]==mx[x])  sn[x]=v;    
        mx[x]=v;   
    }
} 
void mark_min(int x,int v) 
{   
    if(mn[x]<v) 
    {       
        sum[x]+=(ll)mi[x]*(v-mn[x]);     
        if(sm[x]==mn[x]) sm[x]=v;   
        if(mx[x]==mn[x]) mx[x]=v;   
        mn[x]=v; 
    }
}
void pushdown(int x) 
{
    if(add[x]) 
    {
        mark_add(lson,add[x]); 
        mark_add(rson,add[x]); 
        add[x]=0; 
    }
    mark_max(lson,mx[x]),mark_max(rson,mx[x]);    
    mark_min(lson,mn[x]),mark_min(rson,mn[x]);    
}        
void build(int l,int r,int x) 
{
    len[x]=r-l+1;  
    if(l==r) 
    {
        sum[x]=(ll)rd(); 
        mn[x]=mx[x]=sum[x],ma[x]=mi[x]=1;    
        sn[x]=inf,sm[x]=-inf;     
        return; 
    } 
    int mid=(l+r)>>1;  
    build(l,mid,lson);   
    build(mid+1,r,rson);  
    pushup(x);  
}   
void addv(int l,int r,int x,int L,int R,int v) 
{
    if(l>=L&&r<=R)   
    {
        mark_add(x,v);   
        return; 
    }    
    pushdown(x);  
    int mid=(l+r)>>1;     
    if(L<=mid)   
        addv(l,mid,lson,L,R,v); 
    if(R>mid)  
        addv(mid+1,r,rson,L,R,v);  
    pushup(x); 
}
void op_min(int l,int r,int x,int L,int R,int v) 
{
    if(v>=mx[x])   
        return;   
    if(l>=L&&r<=R&&v>sm[x]) 
    {                 
        mark_max(x,v);    
        return; 
    } 
    pushdown(x); 
    int mid=(l+r)>>1;    
    if(L<=mid)   
        op_min(l,mid,lson,L,R,v); 
    if(R>mid)   
        op_min(mid+1,r,rson,L,R,v);  
    pushup(x); 
}
void op_max(int l,int r,int x,int L,int R,int v) 
{      
    if(v<=mn[x])  
        return;    
    if(l>=L&&r<=R&&v<sn[x])  
    {           
        mark_min(x,v);   
        return; 
    }    
    pushdown(x); 
    int mid=(l+r)>>1;   
    if(L<=mid)    
        op_max(l,mid,lson,L,R,v); 
    if(R>mid)   
        op_max(mid+1,r,rson,L,R,v);  
    pushup(x);  
}
void query(int l,int r,int x,int L,int R,int &MIN,int &MAX,ll &SUM) 
{
    if(l>=L&&r<=R)
    {
        MIN=min(MIN,mn[x]); 
        MAX=max(MAX,mx[x]);  
        SUM+=sum[x];  
        return; 
    } 
    pushdown(x); 
    int mid=(l+r)>>1;  
    if(L<=mid)   
        query(l,mid,lson,L,R,MIN,MAX,SUM);  
    if(R>mid)  
        query(mid+1,r,rson,L,R,MIN,MAX,SUM);   
    pushup(x);   
}
int main() 
{    
    // freopen("input.in","r",stdin);     
    n=rd(),build(1,n,1); 
    int m=rd(); 
    for(int i=1;i<=m;++i) 
    {
        int op=rd(),l=rd(),r=rd(),x; 
        if(op==1) 
            x=rd(),addv(1,n,1,l,r,x);    
        if(op==2)       
            x=rd(),op_max(1,n,1,l,r,x);   
        if(op==3)   
            x=rd(),op_min(1,n,1,l,r,x);  
        if(op>=4) 
        { 
            ll SUM=0; 
            int MIN=inf,MAX=-inf; 
            query(1,n,1,l,r,MIN,MAX,SUM);    
            if(op==4)  
                printf("%lld\n",SUM); 
            if(op==5)       
                printf("%d\n",MAX);   
            if(op==6)  
                printf("%d\n",MIN);  
        }
    }
    return 0;     
}

  

posted @ 2020-03-23 23:24  EM-LGH  阅读(193)  评论(0编辑  收藏  举报