通过差分使得区间修改,变成单点修改
/*
gcd(a,b)=gcd(a,b-a);
gcd(a,b,c)=gcd((a,b),(b,c))=gcd((a,b-a),(b,c-b))
=gcd(a,b-a,c-b);
因此W[N]可以差分来求一段序列的最大公约数
==gcd(w[l].sum,gcd(w[l+1]~w[r]))
*/
/*
gcd(a,b)=gcd(a,b-a);
gcd(a,b,c)=gcd((a,b),(b,c))=gcd((a,b-a),(b,c-b))
=gcd(a,b-a,c-b);
因此W[N]可以差分来求一段序列的最大公约数
==gcd(w[l].sum,gcd(w[l+1]~w[r]))
*/
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int N=5000010;
int n,m;
int w[N];
struct node{
int l,r,sum,d;//总和,区间gcd
}tr[N*4];
void pushup(node &u,node &l,node &r){
u.sum=l.sum+r.sum;
u.d=__gcd(l.d,r.d);
}
void pushup(int u){
pushup(tr[u],tr[u*2],tr[u*2+1]);
}
void build(int u,int l,int r){
if(l==r){
int b=w[r]-w[r-1];//差分建
tr[u]={l,r,b,b};
return;
}
tr[u].l=l,tr[u].r=r;
int mid=(l+r)/2;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
void change(int u,int x,int v){
if(tr[u].l==x&&tr[u].r==x){//找到根节点
int b=tr[u].sum+v;
tr[u]={x,x,b,b};
return;
}
int mid=(tr[u].l+tr[u].r)/2;
if(x<=mid) change(u*2,x,v);
else change(u*2+1,x,v);
pushup(u);
}
node query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r) return tr[u];
int mid=(tr[u].l+tr[u].r)/2;
if(r<=mid) return query(u*2,l,r);
else if(l>mid) return query(u*2+1,l,r);
else{//分块
auto left=query(u*2,l,r);
auto right=query(u*2+1,l,r);
node res;
pushup(res,left,right);
return res;
}
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>w[i];
}
build(1,1,n);
while(m--){
char s;int l,r;
cin>>s>>l>>r;
if(s=='Q'){
auto left=query(1,1,l);
node right={0,0,0,0};
if(l+1<=r)
right=query(1,l+1,r);
cout<<abs(__gcd(left.sum,right.d))<<endl;
}
else{
int d;cin>>d;
change(1,l,d);
if(r<n) change(1,r+1,-d);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
solve();
return 0;
}