论文题。
考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记。
我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值。
对于被覆盖一半的区间,讨论一下即可。
对于每个最小值和次小值记录前缀最小值,当前/历史最小值,当到达合法区间的时候:
如果区间最小值>x,直接退出。
如果minv[o]<x<semn[o],那么更新当前的次小值
反之继续向下。
#include<bits/stdc++.h> const int inf=2e9+7; const int N=500005; using namespace std; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } int n,m; struct Segment_Tree_Beats{ #define lson (o<<1) #define rson (o<<1|1) int his[N<<2],pra[N<<2],prb[N<<2],a[N<<2],b[N<<2],minv[N<<2],semn[N<<2]; inline void pushup(int o){ if(minv[lson]==minv[rson])minv[o]=minv[lson],semn[o]=min(semn[lson],semn[rson]); else if(minv[lson]<minv[rson]){minv[o]=minv[lson];semn[o]=min(semn[lson],minv[rson]);} else{minv[o]=minv[rson];semn[o]=min(semn[rson],minv[lson]);} his[o]=min(his[lson],his[rson]); } inline void puttag(int o,int v){ his[o]=min(his[o],minv[o]+v); a[o]+=v;b[o]+=v;minv[o]+=v;semn[o]+=v;semn[o]=min(semn[o],inf); pra[o]=min(pra[o],a[o]); prb[o]=min(prb[o],b[o]); } inline void plus(int o,int ax,int pa,int bx,int pb){ his[o]=min(his[o],minv[o]+pa); pra[o]=min(pra[o],pa+a[o]); prb[o]=min(prb[o],pb+b[o]); a[o]+=ax;b[o]+=bx;minv[o]+=ax;semn[o]+=bx;semn[o]=min(semn[o],inf); } inline void pushdown(int o){ int mmmm=min(minv[lson],minv[rson]); if(minv[lson]==mmmm)plus(lson,a[o],pra[o],b[o],prb[o]);else plus(lson,b[o],prb[o],b[o],prb[o]); if(minv[rson]==mmmm)plus(rson,a[o],pra[o],b[o],prb[o]);else plus(rson,b[o],prb[o],b[o],prb[o]); a[o]=b[o]=pra[o]=prb[o]=0; } inline void build(int o,int l,int r){ if(l==r){ minv[o]=read();his[o]=minv[o];semn[o]=inf; return; } int mid=(l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); pushup(o); } inline void optadd(int o,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr){puttag(o,v);return;} int mid=(l+r)>>1;pushdown(o); if(ql<=mid)optadd(lson,l,mid,ql,qr,v); if(qr>mid)optadd(rson,mid+1,r,ql,qr,v); pushup(o); } inline void dfs(int o,int l,int r,int v){ if(minv[o]>=v)return; if(semn[o]>v){ v-=minv[o];his[o]=min(his[o],minv[o]+v); pra[o]=min(pra[o],a[o]+v); a[o]+=v;minv[o]+=v;return; } int mid=(l+r)>>1;pushdown(o); dfs(lson,l,mid,v);dfs(rson,mid+1,r,v); pushup(o); } inline void change(int o,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr){dfs(o,l,r,v);return;} int mid=(l+r)>>1;pushdown(o); if(ql<=mid)change(lson,l,mid,ql,qr,v); if(qr>mid)change(rson,mid+1,r,ql,qr,v); pushup(o); } inline int querynow(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return minv[o]; int mid=(l+r)>>1,ans=inf;pushdown(o); if(ql<=mid)ans=min(ans,querynow(lson,l,mid,ql,qr)); if(qr>mid)ans=min(ans,querynow(rson,mid+1,r,ql,qr)); return ans; } inline int queryhis(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return his[o]; int mid=(l+r)>>1,ans=inf;pushdown(o); if(ql<=mid)ans=min(ans,queryhis(lson,l,mid,ql,qr)); if(qr>mid)ans=min(ans,queryhis(rson,mid+1,r,ql,qr)); return ans; } }T; int main(){ n=read();m=read(); T.build(1,1,n); while(m--){ int opt=read(),l=read(),r=read(); if(opt==1){int x=read();T.optadd(1,1,n,l,r,x);} if(opt==2){int x=read();T.change(1,1,n,l,r,x);} if(opt==3)printf("%d\n",T.querynow(1,1,n,l,r)); if(opt==4)printf("%d\n",T.queryhis(1,1,n,l,r)); } }