市场
我们不难得到一个简单的算法:维护区间\(\tt min,max,sum\)
对于1.3.4操作,直接打标记,操作即可
关键是如何处理操作2
对于区间\([l,r]\)
- \(\lfloor \frac{\max a_l\sim a_r}{d}\rfloor =\lfloor \frac{\min a_l\sim a_r}{d}\rfloor\)打上区间覆盖标记
- \(\max_{i\in[l,r]} a_i-\lfloor \frac{\max a_l\sim a_r}{d}\rfloor =\min_{i\in[l,r]} a_i-\lfloor \frac{\min a_l\sim a_r}{d}\rfloor\)打上区间减标记
- 递归地进行
下面证明复杂度:
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
T t=0;
char k;
bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define ll long long
const int def=2e9+5;
ll sum[400005],fl[400005];
int s,mx[400005],m,mn[400005],cov[400005];
void pushup(int d){
mx[d]=max(mx[d<<1],mx[d<<1|1]);
mn[d]=min(mn[d<<1],mn[d<<1|1]);
sum[d]=sum[d<<1]+sum[d<<1|1];
}void pushdown(int d,int n){
if(cov[d]!=def){
mx[d]=mn[d]=cov[d];
sum[d]=1ll*cov[d]*n;
if(n!=1){
fl[d<<1]=fl[d<<1|1]=0;
cov[d<<1]=cov[d<<1|1]=cov[d];
}
cov[d]=def;
}
mx[d]+=fl[d];
mn[d]+=fl[d];
sum[d]+=1ll*fl[d]*n;
if(n!=1){
fl[d<<1]+=fl[d];
fl[d<<1|1]+=fl[d];
}fl[d]=0;
}
void build(int l,int r,int d){
cov[d]=def;
if(l==r)mx[d]=mn[d]=sum[d]=read;
else{
int mid=l+r>>1;
build(l,mid,d<<1);
build(mid+1,r,d<<1|1);
pushup(d);
}
}
ll query(int l,int r,int tl,int tr,int d){
if(r<tl||tr<l)return 0;
pushdown(d,tr-tl+1);
if(l<=tl&&tr<=r)return sum[d];
int mid=tl+tr>>1;
return query(l,r,tl,mid,d<<1)+query(l,r,mid+1,tr,d<<1|1);
}
int query_(int l,int r,int tl,int tr,int d){
if(r<tl||tr<l)return def;
pushdown(d,tr-tl+1);
if(l<=tl&&tr<=r)return mn[d];
int mid=tl+tr>>1;
return min(query_(l,r,tl,mid,d<<1),query_(l,r,mid+1,tr,d<<1|1));
}
void add(int l,int r,int c,int tl,int tr,int d){
pushdown(d,tr-tl+1);
if(r<tl||tr<l)return;
if(l<=tl&&tr<=r){fl[d]+=c;pushdown(d,tr-tl+1);return;}
int mid=tl+tr>>1;
add(l,r,c,tl,mid,d<<1);
add(l,r,c,mid+1,tr,d<<1|1);
pushup(d);
}
ll Div(ll x,ll y){return floor(1.0*x/y);}
void divi(int l,int r,int c,int tl,int tr,int d){
pushdown(d,tr-tl+1);
if(r<tl||tr<l)return;
if(l<=tl&&tr<=r){
if(Div(mx[d],c)==Div(mn[d],c)){
cov[d]=Div(mx[d],c);
pushdown(d,tr-tl+1);
return;
}
if(mx[d]-Div(mx[d],c)==mn[d]-Div(mn[d],c)){
fl[d]-=mx[d]-Div(mx[d],c);
pushdown(d,tr-tl+1);
return;
}
}
int mid=tl+tr>>1;
divi(l,r,c,tl,mid,d<<1);
divi(l,r,c,mid+1,tr,d<<1|1);
pushup(d);
}
void pr(int d,int l,int r){
pushdown(d,r-l+1);
if(l==r)printf("%d::",mx[d]);
else{
int mid=l+r>>1;
pr(d<<1,l,mid);
pr(d<<1|1,mid+1,r);
}
}
int main(){
s=read;m=read;
build(1,s,1);
while(m--){
int opt=read,l=read+1,r=read+1;
if(opt==1)add(l,r,read,1,s,1);
if(opt==2)divi(l,r,read,1,s,1);
if(opt==3)printf("%d\n",query_(l,r,1,s,1));
if(opt==4)printf("%lld\n",query(l,r,1,s,1));
// pr(1,1,s);cout<<endl;
}
return 0;
}
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存