线段树每个区间维护上下界以及要整体增加的标记即可,时间复杂度$O(mlog n)$。
#include<cstdio> #define inf 1500000000 int n,m,op,c,d,p; struct Node{int l,r,t;}T[1050000]; inline void read(int&a){ char c;bool f=0;a=0; while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-'))); if(c!='-')a=c-'0';else f=1; while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0'; if(f)a=-a; } inline int min(int a,int b){return a<b?a:b;} inline int max(int a,int b){return a>b?a:b;} inline void up(int x){ T[x].l=min(T[x<<1].l,T[x<<1|1].l); T[x].r=max(T[x<<1].r,T[x<<1|1].r); } void build(int x,int a,int b){ if(a==b){read(T[x].l),T[x].r=T[x].l;return;} int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x); } inline void add1(int x,int p){T[x].l+=p,T[x].r+=p,T[x].t+=p;} inline void make(int x,int l,int r){ T[x].l=min(max(T[x].l,l),r); T[x].r=min(max(T[x].r,l),r); } inline void pb(int x){ if(T[x].t)add1(x<<1,T[x].t),add1(x<<1|1,T[x].t),T[x].t=0; make(x<<1,T[x].l,T[x].r),make(x<<1|1,T[x].l,T[x].r); } void add(int x,int a,int b){ if(c<=a&&b<=d){add1(x,p);return;} pb(x); int mid=(a+b)>>1; if(c<=mid)add(x<<1,a,mid); if(d>mid)add(x<<1|1,mid+1,b); up(x); } void change(int x,int a,int b,int l,int r){ if(c<=a&&b<=d){make(x,l,r);return;} pb(x); int mid=(a+b)>>1; if(c<=mid)change(x<<1,a,mid,l,r); if(d>mid)change(x<<1|1,mid+1,b,l,r); up(x); } int ask(int x,int a,int b){ if(c<=a&&b<=d)return T[x].r; pb(x); int mid=(a+b)>>1,t=-inf; if(c<=mid)t=ask(x<<1,a,mid); if(d>mid)t=max(t,ask(x<<1|1,mid+1,b)); return up(x),t; } int main(){ read(n),read(m),build(1,1,n); while(m--){ read(op),read(c),read(d); if(op==4){printf("%d ",ask(1,1,n));continue;} read(p); if(op==1)add(1,1,n); if(op==2)change(1,1,n,-inf,p); if(op==3)change(1,1,n,p,inf); } return 0; }