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; }