大致题意:
对一数列三种操作:
1.对L,R区间的所有数mod x
2.把a[pos]改成x
3.询问L,R区间的所有数之和
思路:第二第三中操作都很好解决
第一种操作要知道,一个数mod另一个数x,他小于x就不需要模,否则,这个数模后必减小一半以上
所以暴力模操作就可以了,一个数最多模logn次。
复杂度是:nlogn*logn
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<int,int> pii;
template <class T>
inline bool RD(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void PT(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) pt(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e5+100;
int maxn[N<<2];
ll sum[N<<2];
int n,m;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
inline void pushup(int rt){
maxn[rt] = max(maxn[ls],maxn[rs]);
sum[rt] = sum[ls]+sum[rs];
}
void build(int l,int r,int rt){
if( l == r){
RD(maxn[rt]);
sum[rt] = maxn[rt];
return ;
}
int m = (l+r)>>1;
build(l,m,ls);
build(m+1,r,rs);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
if( L <= l && r <= R){
return sum[rt];
}
int m = (l+r)>>1;
ll ans = 0;
if( L <= m) ans += query(L,R,l,m,ls);
if( R > m) ans += query(L,R,m+1,r,rs);
return ans;
}
void getmod(int L,int R,int mod,int l,int r,int rt){
if( maxn[rt] < mod) return;
if( l == r ){
maxn[rt] %= mod;
sum[rt] %= mod;
return ;
}
int m = (l+r)>>1;
if( L <= m) getmod(L,R,mod,l,m,ls);
if( R > m) getmod(L,R,mod,m+1,r,rs);
pushup(rt);
}
void update(int pos,int x,int l,int r,int rt){
if( l == r) {
sum[rt] = x;
maxn[rt] = x;
return;
}
int m = (l+r)>>1;
if( pos <= m ) update(pos,x,l,m,ls);
else update(pos,x,m+1,r,rs);
pushup(rt);
}
int main(){
cin>>n>>m;
build(root);
while(m--){
int op; RD(op);
if( op == 1){
int l,r;
RD(l),RD(r);
printf("%I64d\n",query(l,r,root));
}
else if( op == 2 ){
int l,r,mod;
scanf("%d%d%d",&l,&r,&mod);
getmod(l,r,mod,root);
}
else{
int pos,x;
scanf("%d%d",&pos,&x);
update(pos,x,root);
}
}
}