zoukankan      html  css  js  c++  java
  • BZOJ4695 最假女选手

    Description

    在刚刚结束的水题嘉年华的压轴节目放水大赛中,wyywyy如愿以偿的得到了最假女选手的奖项。但是作为主办人的C_SUNSHINE为了证明wyywyy确实在放水,决定出一道基础题考察wyywyy的姿势水平。给定一个长度为 $N$序列,编号从$1$ 到 $N$。要求支持下面几种操作:
    1.给一个区间$[L,R]$ 加上一个数$x$
    2.把一个区间$[L,R]$ 里小于$x$ 的数变成$x$
    3.把一个区间$[L,R]$ 里大于$x$ 的数变成$x$
    4.求区间$[L,R]$ 的和
    5.求区间$[L,R]$ 的最大值
    6.求区间$[L,R]$ 的最小值

    Solution

    吉司机线段树板题

    维护区间最大值,最小值,次大值,次小值,最大值加标记,最小值加标记,非最值的加标记

    有可能出现区间最大值与最小值相等、最大值与次小值相等,最小值与次大值相等的情况,需要特判

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,m;
    const int inf=0x7f7f7f7f;
    inline int read(){
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return f*w;
    }
    namespace SGT{
        int maxx[2000005],minn[2000005],mx[2000005],mn[2000005],cmx[2000005],cmn[2000005];
        long long sum[2000005],plz1[2000005],plz2[2000005],plz3[2000005];
        void pushup(int i){
            sum[i]=sum[i<<1]+sum[i<<1|1],maxx[i]=max(maxx[i<<1],maxx[i<<1|1]),minn[i]=min(minn[i<<1],minn[i<<1|1]);
            if(maxx[i<<1]==maxx[i<<1|1])cmx[i]=cmx[i<<1]+cmx[i<<1|1],mx[i]=max(mx[i<<1],mx[i<<1|1]);
            else cmx[i]=maxx[i<<1]>maxx[i<<1|1]?cmx[i<<1]:cmx[i<<1|1],mx[i]=max(mx[i<<1],max(mx[i<<1|1],min(maxx[i<<1],maxx[i<<1|1])));
            if(minn[i<<1]==minn[i<<1|1])cmn[i]=cmn[i<<1]+cmn[i<<1|1],mn[i]=min(mn[i<<1],mn[i<<1|1]);
            else cmn[i]=minn[i<<1]<minn[i<<1|1]?cmn[i<<1]:cmn[i<<1|1],mn[i]=min(mn[i<<1],min(mn[i<<1|1],max(minn[i<<1],minn[i<<1|1])));
        }
        void add(int i,int l,int r,int a1,int a2,int a3){
            if(minn[i]==maxx[i])a1==a3?a1=a2:a2=a1,sum[i]+=1ll*a1*cmn[i];
            else sum[i]+=1ll*a1*cmn[i]+1ll*a2*cmx[i]+1ll*a3*(r-l+1-cmx[i]-cmn[i]);
            if(mn[i]==maxx[i])mn[i]+=a2;
            else if(mn[i]!=inf)mn[i]+=a3;
            if(mx[i]==minn[i])mx[i]+=a1;
            else if(mx[i]!=-inf)mx[i]+=a3;
            maxx[i]+=a2,minn[i]+=a1,plz1[i]+=a1,plz2[i]+=a2,plz3[i]+=a3;
        }
        void pushdown(int i,int l,int r){
            int t1=min(minn[i<<1],minn[i<<1|1]),t2=max(maxx[i<<1],maxx[i<<1|1]),mid=l+r>>1;
            add(i<<1,l,mid,minn[i<<1]==t1?plz1[i]:plz3[i],maxx[i<<1]==t2?plz2[i]:plz3[i],plz3[i]);
            add(i<<1|1,mid+1,r,minn[i<<1|1]==t1?plz1[i]:plz3[i],maxx[i<<1|1]==t2?plz2[i]:plz3[i],plz3[i]);
            plz1[i]=plz2[i]=plz3[i]=0;
        }
        void build(int i,int l,int r){
            if(l==r){sum[i]=maxx[i]=minn[i]=read(),mx[i]=-inf,mn[i]=inf,cmx[i]=cmn[i]=1;return;}
            int mid=l+r>>1;
            build(i<<1,l,mid),build(i<<1|1,mid+1,r),pushup(i);
        }
        void update(int i,int l,int r,int L,int R,int x){
            if(L<=l&&r<=R){add(i,l,r,x,x,x);return;}
            int mid=l+r>>1;
            pushdown(i,l,r);
            if(L<=mid)update(i<<1,l,mid,L,R,x);
            if(R>mid)update(i<<1|1,mid+1,r,L,R,x);
            pushup(i);
        }
        void updatemax(int i,int l,int r,int L,int R,int x){
            if(minn[i]>=x)return;
            if(x<mn[i]&&L<=l&&r<=R){add(i,l,r,x-minn[i],0,0);return;}
            int mid=l+r>>1;
            pushdown(i,l,r);
            if(L<=mid)updatemax(i<<1,l,mid,L,R,x);
            if(R>mid)updatemax(i<<1|1,mid+1,r,L,R,x);
            pushup(i);
        }
        void updatemin(int i,int l,int r,int L,int R,int x){
            if(maxx[i]<=x)return;
            if(x>mx[i]&&L<=l&&r<=R){add(i,l,r,0,x-maxx[i],0);return;}
            int mid=l+r>>1;
            pushdown(i,l,r);
            if(L<=mid)updatemin(i<<1,l,mid,L,R,x);
            if(R>mid)updatemin(i<<1|1,mid+1,r,L,R,x);
            pushup(i);
        }
        long long querysum(int i,int l,int r,int L,int R){
            if(L<=l&&r<=R)return sum[i];
            int mid=l+r>>1;
            long long ret=0;
            pushdown(i,l,r);
            if(L<=mid)ret+=querysum(i<<1,l,mid,L,R);
            if(R>mid)ret+=querysum(i<<1|1,mid+1,r,L,R);
            return ret;
        }
        int querymax(int i,int l,int r,int L,int R){
            if(L<=l&&r<=R)return maxx[i];
            int mid=l+r>>1,ret=-inf;
            pushdown(i,l,r);
            if(L<=mid)ret=max(ret,querymax(i<<1,l,mid,L,R));
            if(R>mid)ret=max(ret,querymax(i<<1|1,mid+1,r,L,R));
            return ret;
        }
        int querymin(int i,int l,int r,int L,int R){
            if(L<=l&&r<=R)return minn[i];
            int mid=l+r>>1,ret=inf;
            pushdown(i,l,r);
            if(L<=mid)ret=min(ret,querymin(i<<1,l,mid,L,R));
            if(R>mid)ret=min(ret,querymin(i<<1|1,mid+1,r,L,R));
            return ret;
        }
    }
    int main(){
        n=read(),SGT::build(1,1,n),m=read();
        for(;m;m--){
            int opt=read();
            if(opt==1){
                int l=read(),r=read(),x=read();
                SGT::update(1,1,n,l,r,x);
            }
            else if(opt==2){
                int l=read(),r=read(),x=read();
                SGT::updatemax(1,1,n,l,r,x);
            }
            else if(opt==3){
                int l=read(),r=read(),x=read();
                SGT::updatemin(1,1,n,l,r,x);
            }
            else if(opt==4){
                int l=read(),r=read();
                printf("%lld
    ",SGT::querysum(1,1,n,l,r));
            }
            else if(opt==5){
                int l=read(),r=read();
                printf("%d
    ",SGT::querymax(1,1,n,l,r));
            }
            else{
                int l=read(),r=read();
                printf("%d
    ",SGT::querymin(1,1,n,l,r));
            }
        }
        return 0;
    }
    最假女选手
  • 相关阅读:
    Python开发——数据类型【字典】
    Python开发——数据类型【元祖】
    Python开发——数据类型【列表】
    Python开发——基础
    Python开发——数据类型【运算符】
    c#中IList<T>与List<T>
    观察者模式(Observer Pattern)
    中介者模式(Mediator Pattern)
    策略模式(Strategy Pattern)
    命令模式
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14521350.html
Copyright © 2011-2022 走看看