分块+树状数组
#include<bits/stdc++.h>
using namespace std;
inline long long read()
{
long long x = 0;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == 'Q' || ch == 'C')return ch;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
inline long long gcd(long long a , long long b)
{
if(a < 0 || b < 0)return gcd(abs(a) , abs(b));
return b > 0 ? gcd(b , a % b) : a;
}
const int MAXN = 5e5 + 5;
long long n , m , l , r , d;
long long lowbit(long long x){return x & (-x);}
long long cl[MAXN];
inline void treadd(long long x , long long d)
{
while(x <= n)
{
cl[x] += d;
x += lowbit(x);
}
}
inline long long trequery(long long x)
{
long long res = 0;
while(x)
{
res += cl[x];
x -= lowbit(x);
}
return res;
}
long long block , num;
long long st[MAXN] , ed[MAXN];
long long pos[MAXN];
long long al[MAXN];
long long s;
long long bl[MAXN];
void build()
{
block = sqrt(n);
num = sqrt(n);
if(n % block)num++;
for(int i = 1;i <= num;i++)
{
st[i] = (i - 1) * block + 1;
ed[i] = i * block;
}
ed[num] = n;
for(int i = 1;i <= n;i++)pos[i] = (i - 1) / block + 1;
long long p;
for(int i = 1;i <= num;i++)
{
p = al[st[i]];
for(int j = st[i] + 1;j <= ed[i];j++)
{
p = gcd(p , al[j]);
}
bl[i] = p;
}
return;
}
void Add(long long x , long long d)
{
al[x] += d;
long long p = pos[x];
long long ans = al[st[p]];
// cout << ans << endl;
for(int i = st[p] + 1;i <= ed[p];i++)
{
ans = gcd(ans , al[i]);
// cout << ans << endl;
}
bl[p] = ans;
}
long long query(long long l , long long r)
{
long long ans = 0;
if(r - l + 1 <= block)
{
ans = al[l];
for(int i = l + 1;i <= r;i++)
{
ans = gcd(ans , al[i]);
}
return ans;
}
long long p = pos[l] , q = pos[r];
if(l != st[p])
{
ans = al[l++];
while(l <= ed[p])ans = gcd(ans , al[l++]);
p++;
}
if(r != ed[q])
{
if(!ans)ans = al[r--];
while(r >= st[q])ans = gcd(ans , al[r--]);
q--;
}
if(!ans)ans = bl[p];
for(int i = p + 1;i <= q;i++)ans = gcd(ans , bl[i]);
return ans;
}
long long sum , bgn;
int main()
{
n = read();
m = read();
for(int i = 1;i <= n;i++)al[i] = read();
bgn = al[1];
for(int i = n;i >= 1;i--)al[i] -= al[i - 1];
for(int i = n;i >= 1;i--)cl[i] = al[i];
build();
for(int i = 1;i <= m;i++)
{
s = read();
if(s == 'Q')
{
l = read();
r = read();
sum = trequery(l);
if(l != 1)sum += bgn;
sum = gcd(sum , query(l + 1 , r));
printf("%lld\n" , sum);
}
else
{
l = read();
r = read();
d = read();
Add(l , d);
treadd(l , d);
if(r == n)continue;
Add(r + 1 , -d);
treadd(r + 1 , -d);
}
}
return 0;
}