4695: 最假女选手
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 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
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 500005
using 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]");
}
}