gcd
(
a
,
b
)
=
gcd
(
a
,
b
−
a
)
\gcd(a,b)=\gcd(a, b-a)
gcd(a,b)=gcd(a,b−a)
gcd
(
a
,
b
,
c
)
=
gcd
(
a
,
b
−
a
,
c
−
b
)
\gcd(a,b,c) = \gcd(a,b-a, c-b)
gcd(a,b,c)=gcd(a,b−a,c−b)
gcd
(
a
1
,
a
2
,
⋯
 
,
a
n
)
=
gcd
(
a
1
,
a
2
−
a
1
,
a
3
−
a
2
,
⋯
 
,
a
n
−
a
n
−
1
)
\gcd(a_1,a_2,\cdots,a_n) = \gcd(a_1, a_2-a_1, a_3-a_2,\cdots,a_n-a_{n-1})
gcd(a1,a2,⋯,an)=gcd(a1,a2−a1,a3−a2,⋯,an−an−1)
知道了这个性质我们可以开一个
B
[
]
B[\ \ ]
B[]数组,表示原序列的差分序列,用线段数维护
B
B
B的区间最大公约数
对于询问“Q l r”等于求出
gcd
(
a
[
l
]
,
q
u
e
r
y
(
1
,
l
+
1
,
r
)
)
\gcd(a[l], query(1,l+1, r))
gcd(a[l],query(1,l+1,r))
对于询问"C l r d"等于
B
[
l
]
B[l]
B[l]加上
d
d
d,
B
[
r
+
1
]
B[r+1]
B[r+1]减去
d
d
d,只需两次线段数的单点修改即可(线段树单点修改模板),对于原序列中
A
A
A的值,我们可以用一个“区间修改+单点查询”的树状数组来维护(树状数组区间修改+单点查询模板)
code
#include<bits/stdc++.h>usingnamespace std;constint maxn =5e5+100;typedeflonglong LL;template<typename T>inlinevoidread(T &s){
s =0;
T w =1, ch =getchar();while(!isdigit(ch)){if(ch =='-') w =-1; ch =getchar();}while(isdigit(ch)){ s =(s <<1)+(s <<3)+(ch ^48); ch =getchar();}
s *= w;}
LL n, m;
LL a[maxn], b[maxn], c[maxn];// 原数组,差分数组,增量数组(树状数组) struct node {
LL l, r;
LL dat;} t[maxn *4];inline LL gcd(LL x, LL y){return y ?gcd(y, x % y): x;}inlinevoidbuild(LL p, LL l, LL r){
t[p].l = l, t[p].r = r;if(l == r){ t[p].dat = b[l];return;}
LL mid =(l + r)>>1;build(p<<1, l, mid);build(p<<1|1, mid +1, r);
t[p].dat =gcd(t[p<<1].dat, t[p<<1|1].dat);}inlinevoidchange(LL p, LL x, LL val){if(t[p].l == t[p].r){ t[p].dat += val;return;}
LL mid =(t[p].l + t[p].r)>>1;if(x <= mid)change(p<<1, x, val);elsechange(p<<1|1, x, val);
t[p].dat =gcd(t[p<<1].dat, t[p<<1|1].dat);}inline LL query(LL p, LL l, LL r){if(l <= t[p].l && r >= t[p].r)return t[p].dat;
LL mid =(t[p].l + t[p].r)>>1;
LL val =0;if(l <= mid) val =gcd(val,query(p<<1, l, r));if(r > mid) val =gcd(val,query(p<<1|1, l, r));returnabs(val);}inline LL lowbit(LL x){return x &-x;}inlinevoidadd(LL x, LL val){for(; x <= n; x +=lowbit(x))
c[x]+= val;}inline LL ask(LL x){
LL ans =0;for(; x; x -=lowbit(x))
ans += c[x];return ans;}intmain(){read(n),read(m);for(LL i =1; i <= n;++i){read(a[i]);
b[i]= a[i]- a[i-1];}build(1,1, n);for(LL i =1; i <= m;++i){char opt[2]; LL l, r, val;scanf("%s", opt);if(opt[0]=='Q'){read(l),read(r);
LL now = a[l]+ask(l);printf("%lld\n",gcd(now,query(1, l+1, r)));}else{read(l),read(r),read(val);add(l, val);add(r +1,-val);change(1, l, val);if(r < n)change(1, r +1,-val);}}return0;}