BZOJ 4695

来源:互联网 发布:2k17德拉蒙德格林数据 编辑:程序博客网 时间:2024/06/10 17:39

4695: 最假女选手

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 126  Solved: 23
[Submit][Status][Discuss]

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] 的最小值

Input

第一行一个整数 N表示序列长度。
第二行N 个整数Ai 表示初始序列。
第三行一个整数M 表示操作个数。
接下来M 行,每行三或四个整数,第一个整数Tp 表示操作类型,接下来L,R,X 或L,R 表述操作数。
1<=tp<=6,N,M<=5*10^5,|Ai|<=10^8
Tp=1时,|x|<=1000
Tp=2或3时,|x|<=10^8

Output

对于每个4,5,6类型的操作输出一行一个整数表示答案。

Sample Input

2
1 2
2
2 1 2 2
4 1 2

Sample Output

4

1操作好搞

2操作就维护一个次大值,一个最大值和最大值出现次数(复杂度证明在传送门)

  在x>=最大值时return

  在x<次大值时继续递归modify

  在次大值<=x<最大值时打上标记

  更新时很恶心,先要更新sum,然后要用x去更新最大值,最小值和次小值

  如果最小值==最大值,说明这个区间内数已经相同了,就需要再次修改次大次小值

  要把3操作的标记更新.

其他操作就随意脑补一下好了

PS:我好像写丑了...加了读入优化,BZOJ续了1s才过...

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define inf (1<<30)#define maxn 500005using namespace std;typedef long long ll;struct segtree{    ll add,sum;    int mntox,mxtox,mxs,mns,mx1,mx2,mn1,mn2,l,r;    void clear(){mx1=mx2=-inf;mn1=mn2=inf;sum=add=mxs=mns=0;mntox=-inf,mxtox=inf;}}s[maxn<<2];int a[maxn],n,m;int inline read(){    register char act=0;    register int f=1,x=0;    while(act=getchar(),act<'0'&&act!='-');    if(act=='-')f=-1,act=getchar();    x=act-'0';    while(act=getchar(),act>='0')x=x*10+act-'0';    return x*f;} bool updmax(int o,int mxtox){    if(s[o].mx1<=mxtox)return 0;    if(s[o].mx2<mxtox){//      printf("max{%d,%d,(%d,%d)}",s[o].mxs,s[o].mx1,s[o].l,s[o].r);        s[o].sum=s[o].sum-(ll)s[o].mxs*s[o].mx1+(ll)s[o].mxs*mxtox;        s[o].mn1=min(s[o].mn1,s[o].mx1=mxtox);        s[o].mn2=min(s[o].mn2,mxtox);        if(s[o].mn1==mxtox)s[o].mn2=inf,s[o].mx2=-inf,s[o].mxs=s[o].mns=s[o].r-s[o].l+1;        s[o].mntox=min(s[o].mxtox=min(s[o].mxtox,mxtox),s[o].mntox);        return 0;    }    return 1;}bool updmin(int o,int mntox){    if(s[o].mn1>=mntox)return 0;    if(s[o].mn2>mntox){//      printf("min{%d,%d,(%d,%d)}",s[o].mns,s[o].mn1,s[o].l,s[o].r);        s[o].sum=s[o].sum-(ll)s[o].mns*s[o].mn1+(ll)s[o].mns*mntox;        s[o].mx1=max(s[o].mx1,s[o].mn1=mntox);        s[o].mx2=max(s[o].mx2,mntox);        if(s[o].mx1==mntox)s[o].mx2=-inf,s[o].mn2=inf,s[o].mxs=s[o].mns=s[o].r-s[o].l+1;        s[o].mxtox=max(s[o].mntox=max(s[o].mntox,mntox),s[o].mxtox);        return 0;    }    return 1;}void xadd(int& x,int y){    if(x==inf||x==-inf)return ;    x+=y;}void pushdown(int o){    if(s[o].add){        s[o<<1].add+=s[o].add;        s[o<<1].sum+=(ll)s[o].add*(s[o<<1].r-s[o<<1].l+1);        s[o<<1].mx1+=s[o].add,s[o<<1].mn1+=s[o].add;        xadd(s[o<<1].mxtox,s[o].add),xadd(s[o<<1].mntox,s[o].add);        xadd(s[o<<1].mx2,s[o].add),xadd(s[o<<1].mn2,s[o].add);                 s[o<<1|1].add+=s[o].add;        s[o<<1|1].sum+=(ll)s[o].add*(s[o<<1|1].r-s[o<<1|1].l+1);        s[o<<1|1].mx1+=s[o].add,s[o<<1|1].mn1+=s[o].add;        xadd(s[o<<1|1].mxtox,s[o].add),xadd(s[o<<1|1].mntox,s[o].add);        xadd(s[o<<1|1].mx2,s[o].add),xadd(s[o<<1|1].mn2,s[o].add);                 s[o].add=0;    }    if(s[o].mxtox!=inf){        updmax(o<<1,s[o].mxtox);        updmax(o<<1|1,s[o].mxtox);        s[o].mxtox=inf;    }    if(s[o].mntox!=-inf){        updmin(o<<1,s[o].mntox);        updmin(o<<1|1,s[o].mntox);        s[o].mntox=-inf;    }}void pushup(ll o){    int ls=o<<1,rs=o<<1|1;    s[o].sum=s[ls].sum+s[rs].sum+(ll)s[o].add*(s[o].r-s[o].l+1);    s[o].mx1=max(s[ls].mx1,s[rs].mx1);    s[o].mx2=max(s[ls].mx2,s[rs].mx2);    s[o].mxs=s[o].mns=0;    if(s[o].mx1==s[ls].mx1)s[o].mxs+=s[ls].mxs;    else if(s[o].mx2<s[ls].mx1)s[o].mx2=s[ls].mx1;    if(s[o].mx1==s[rs].mx1)s[o].mxs+=s[rs].mxs;    else if(s[o].mx2<s[rs].mx1)s[o].mx2=s[rs].mx1;    s[o].mx1+=s[o].add;         s[o].mn1=min(s[ls].mn1,s[rs].mn1);    s[o].mn2=min(s[ls].mn2,s[rs].mn2);    if(s[o].mn1==s[ls].mn1)s[o].mns+=s[ls].mns;    else if(s[o].mn2>s[ls].mn1)s[o].mn2=s[ls].mn1;    if(s[o].mn1==s[rs].mn1)s[o].mns+=s[rs].mns;    else if(s[o].mn2>s[rs].mn1)s[o].mn2=s[rs].mn1;    s[o].mn1+=s[o].add;    xadd(s[o].mn2,s[o].add);    xadd(s[o].mx2,s[o].add);}void build(int o,int l,int r){    s[o].l=l,s[o].r=r;    s[o].clear();    if(l==r){        s[o].mx1=s[o].mn1=a[l];        s[o].mxs=1,s[o].mns=1;        s[o].sum=a[l];        return ;    }    int mid=l+r>>1;    build(o<<1,l,mid);    build(o<<1|1,mid+1,r);    pushup(o);}void modify1(int o,int ql,int qr,int a){    if(ql<=s[o].l&&s[o].r<=qr){        s[o].sum+=(ll)(s[o].r-s[o].l+1)*a;        s[o].mx1+=a,s[o].mxtox+=a;        s[o].mn1+=a,s[o].mntox+=a;        xadd(s[o].mx2,a);        xadd(s[o].mn2,a);        s[o].add+=a;        return ;    }    pushdown(o);    if(ql<=s[o<<1].r)modify1(o<<1,ql,qr,a);    if(s[o<<1|1].l<=qr)modify1(o<<1|1,ql,qr,a);    pushup(o);}void modify2(ll o,ll ql,ll qr,ll a){    if(ql<=s[o].l&&s[o].r<=qr&&!updmin(o,a))        return ;    pushdown(o);    if(ql<=s[o<<1].r)modify2(o<<1,ql,qr,a);    if(s[o<<1|1].l<=qr)modify2(o<<1|1,ql,qr,a);      pushup(o);}void modify3(ll o,ll ql,ll qr,ll a){//  printf("[%d,%d,%d]",s[o].l,s[o].r,s[o].mx1);    if(ql<=s[o].l&&s[o].r<=qr&&!updmax(o,a))        return ;    pushdown(o);    if(ql<=s[o<<1].r)modify3(o<<1,ql,qr,a);    if(s[o<<1|1].l<=qr)modify3(o<<1|1,ql,qr,a);    pushup(o);}ll querysum(int o,int ql,int qr){    if(ql<=s[o].l&&s[o].r<=qr)return s[o].sum;    pushdown(o);    ll ans=0;    if(ql<=s[o<<1].r)ans+=querysum(o<<1,ql,qr);    if(s[o<<1|1].l<=qr)ans+=querysum(o<<1|1,ql,qr);    return ans;}int querymx(int o,int ql,int qr){    if(ql<=s[o].l&&s[o].r<=qr)return s[o].mx1;    pushdown(o);    int ans=-inf;    if(ql<=s[o<<1].r)ans=max(ans,querymx(o<<1,ql,qr));    if(s[o<<1|1].l<=qr)ans=max(ans,querymx(o<<1|1,ql,qr));    return ans;}int querymn(int o,int ql,int qr){    if(ql<=s[o].l&&s[o].r<=qr)return s[o].mn1;    pushdown(o);    int ans=inf;    if(ql<=s[o<<1].r)ans=min(ans,querymn(o<<1,ql,qr));    if(s[o<<1|1].l<=qr)ans=min(ans,querymn(o<<1|1,ql,qr));    return ans;}int main(){    n=read();    for(int i=1;i<=n;++i)a[i]=read();    build(1,1,n);    m=read();     for(int i=1;i<=m;++i){        int tp,l,r,x;tp=read();        if(tp<=3)l=read(),r=read(),x=read();        else l=read(),r=read();        if(tp==1)modify1(1,l,r,x);        else if(tp==2)modify2(1,l,r,x);        else if(tp==3)modify3(1,l,r,x);        else if(tp==4)printf("%lld\n",querysum(1,l,r));        else if(tp==5)printf("%d\n",querymx(1,l,r));        else if(tp==6)printf("%d\n",querymn(1,l,r));//      printf("[%d:%d]\n",s[1].mn1,s[1].sum);//      printf("[ok]");    }}


0 0
原创粉丝点击