• 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
    ",SUM); 
                if(op==5)       
                    printf("%d
    ",MAX);   
                if(op==6)  
                    printf("%d
    ",MIN);  
            }
        }
        return 0;     
    }
    

      

  • 相关阅读:
    tomcat源码springboot搭建的跑包含websocket的项目
    tomcat源码ant编译
    职责链设计模式最简单的实例
    完美解决asp.net core 3.1 两个AuthenticationScheme(cookie,jwt)共存在一个项目中
    基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
    Html5 在手机端 input 默认弹出英文键盘
    Html Table 表格 画斜线
    多个单列索引和联合索引的区别
    springboot常用功能
    前端代码评审(Code Review)
  • 原文地址:https://www.cnblogs.com/guangheli/p/12556112.html
Copyright © 2020-2023  润新知