题目链接:https://www.acwing.com/problem/content/description/247/
更相减损术:(gcd(a,b) = gcd(a,a - b))
可以扩展到 (n) 个数,(gcd(a,b,c) = gcd(a,b-a,c-b))
于是可以用线段树维护(a)的差分数组(b),查询时的答案即为(gcd(a[L],query(l+1,r))
细节:
- (gcd(a,b) = gcd(a,-b)), 对结果取负
- (gcd)中(a,b)为(0)没有关系
- (long long)
- (r+1)可能越界,(n+1) 即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 500010;
int n, m;
ll a[maxn], b[maxn], c[maxn];
char s[10];
struct SEG{
ll gc;
}t[maxn << 2];
ll gcd(ll x, ll y){ return y? gcd(y, x % y) : x; }
void add(ll x, ll y){
for(; x <=n ; x += x & (-x))
c[x] += y;
}
ll ask(ll x){
ll sum = 0;
for(; x ; x -= x & (-x))
sum += c[x];
return sum;
}
void pushup(int i){
t[i].gc = gcd(t[i << 1].gc, t[i << 1 | 1].gc);
}
void build(int i, int l, int r){
if(l == r){
t[i].gc = b[l];
return;
}
int mid = (l + r) >> 1;
build(i << 1, l, mid); build(i << 1 | 1, mid + 1, r);
pushup(i);
}
void modify(int i, int l, int r, int p, ll k){
if(l == r){
t[i].gc += k;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) modify(i << 1, l, mid , p, k);
else modify(i << 1 | 1, mid + 1, r, p ,k);
pushup(i);
}
ll query(int i, int l, int r, int x, int y){
if(x > y) return 0;
if(x <= l && r <= y){
return t[i].gc;
}
int mid = (l + r) >> 1;
if(y <= mid) return query(i << 1, l, mid, x, y);
else if(x > mid) return query(i << 1 | 1, mid + 1 , r, x, y);
else return gcd(query(i << 1, l, mid, x, y), query(i << 1 | 1, mid + 1 , r, x, y));
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf("%lld",&a[i]);
b[i] = a[i] - a[i - 1];
add(i, b[i]);
}
b[++n] = -b[n-1];
build(1, 1, n);
int x, y; ll d;
for(int i = 1; i <= m; ++i){
scanf("%s%d%d", s, &x, &y);
if(s[0] == 'Q'){
ll A = ask(x);
ll B = query(1, 1, n, x + 1, y);
printf("%lld
", abs(gcd(A, B)));
} else{
scanf("%lld", &d);
modify(1, 1, n, x, d);
modify(1, 1, n, y + 1, -d);
add(x, d); add(y + 1, -d);
}
}
return 0;
}