线段树
这题标签错了吧。明明是线段树裸题啊
维护区间和,区间最小值,区间加修改,基本操作嘛,注意开longlong
一遍过,直接上代码吧。。
#include<iostream>
#include<cstdio>
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
#define LL long long
using namespace std;
const int N=200005;
int n,q;
LL tr[N<<2],laz[N<<2],mi[N<<2];
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return w*s;
}
inline void update(int k){
tr[k]=tr[ls]+tr[rs];
mi[k]=min(mi[ls],mi[rs]);
}
inline void down(int k,int l,int r){
laz[ls]+=laz[k];laz[rs]+=laz[k];
tr[ls]+=laz[k]*(mid-l+1);mi[ls]+=laz[k];
tr[rs]+=laz[k]*(r-mid);mi[rs]+=laz[k];
laz[k]=0;
}
void build(int k,int l,int r){
if(l==r){
tr[k]=mi[k]=read();
return ;
}
build(lson);build(rson);
update(k);
}
void change(int k,int l,int r,int x,int y,int z){
if(l==x&&y==r){
tr[k]+=(LL)z*(r-l+1);
mi[k]+=z;
laz[k]+=z;
return ;
}
if(laz[k])down(k,l,r);
if(y<=mid)change(lson,x,y,z);
else if(x>mid)change(rson,x,y,z);
else change(lson,x,mid,z),change(rson,mid+1,y,z);
update(k);
}
LL ask(int k,int l,int r,int x,int y){
if(l==x&&y==r){
return tr[k];
}
if(laz[k])down(k,l,r);
if(y<=mid)return ask(lson,x,y);
else if(x>mid)return ask(rson,x,y);
else return ask(lson,x,mid)+ask(rson,mid+1,y);
}
LL query(int k,int l,int r,int x,int y){
if(l==x&&y==r){
return mi[k];
}
if(laz[k])down(k,l,r);
if(y<=mid)return query(lson,x,y);
else if(x>mid)return query(rson,x,y);
else return min(query(lson,x,mid),query(rson,mid+1,y));
}
int main(){
n=read();q=read();
build(1,1,n);
char ch[5];
int x,y,z;
while(q--){
scanf("%s",ch+1);
x=read();y=read();
if(ch[1]=='P'){z=read();change(1,1,n,x,y,z);}
else if(ch[1]=='M'){printf("%lld\n",query(1,1,n,x,y));}
else if(ch[1]=='S'){printf("%lld\n",ask(1,1,n,x,y));}
}
return 0;
}