区间求和,单点修改,单点取模。
单点取模直接暴力取模,存一个max,如果max<mod,那么无需取模。
#include<cstdio>
#include<iostream>
using namespace std;
const int N=100005;
typedef long long ll;
int n,m;
struct node{
int max;
ll sum;
}t[N<<2];
int a[N];
int read(){
int num=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
num=num*10+c-'0';
c=getchar();
}
return f*num;
}
void pushup(int k){
t[k].max=max(t[k<<1].max,t[k<<1|1].max);
t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
}
void build(int k,int l,int r){
if(l==r){
t[k].max=t[k].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
ll query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){
return t[k].sum;
}
int mid=(l+r)>>1;
ll res=0;
if(x<=mid) res+=query(k<<1,l,mid,x,y);
if(y>mid) res+=query(k<<1|1,mid+1,r,x,y);
return res;
}
void update(int k,int l,int r,int x,int y,int mod){
if(t[k].max<mod) return;
if(l==r){
t[k].sum%=mod;
t[k].max%=mod;
return;
}
int mid=(l+r)>>1;
if(x<=mid&&t[k<<1].max>=mod) update(k<<1,l,mid,x,y,mod);
if(y>mid&&t[k<<1|1].max>=mod) update(k<<1|1,mid+1,r,x,y,mod);
pushup(k);
}
void change(int k,int l,int r,int x,int v){
if(l==r){
t[k].sum=t[k].max=v;
return;
}
int mid=(l+r)>>1;
if(x<=mid) change(k<<1,l,mid,x,v);
if(x>mid) change(k<<1|1,mid+1,r,x,v);
pushup(k);
}
int main(){
n=read(); m=read();
for(int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
for(int i=1;i<=m;i++){
int type=read();
if(type==1){
int l=read(),r=read();
printf("%lld
",query(1,1,n,l,r));
}
else if(type==2){
int l=read(),r=read(),x=read();
update(1,1,n,l,r,x);
}
else{
int l=read(),x=read();
change(1,1,n,l,x);
}
}
return 0;
}