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\n",SGT::querysum(1,1,n,l,r));
        }
        else if(opt==5){
            int l=read(),r=read();
            printf("%d\n",SGT::querymax(1,1,n,l,r));
        }
        else{
            int l=read(),r=read();
            printf("%d\n",SGT::querymin(1,1,n,l,r));
        }
    }
    return 0;
}
最假女选手

 

posted @ 2021-03-11 23:32  QDK_Storm  阅读(80)  评论(0编辑  收藏  举报