思路:求l~r的a数组的gcd,等价于求al与各差分ai的gcd.证明:辗转相除法.
详细的讲下吧.假如d是al,al+1...ar的gcd,那么它一定是al,al+1-al,al+2-al+1...的公约数.同理后面可得前面.
那么原题就可以用线段树维护差分数组的gcd即可.
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
ll w[N],s[N];
struct node{
    ll l,r,sum,d;    
}tr[N*4];

void pushup(node &u,node &left,node &right)
{
    u.sum=left.sum+right.sum;
    u.d=__gcd(left.d,right.d);
}

void pushup(ll u)
{
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

void build(ll u,ll l,ll r)
{
    if(l==r)
    {
        tr[u]={l,r,w[l],w[l]};
    }
    else
    {
        tr[u]={l,r};
        ll mid=tr[u].l+tr[u].r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}

void modify(ll u,ll x,ll v)
{
    if(tr[u].l==tr[u].r&&tr[u].l==x)
    {
        tr[u]={x,x,tr[u].sum+v,tr[u].sum+v};
        return;
    }
    else
    {
        ll mid=tr[u].l+tr[u].r>>1;
        if(x<=mid)  modify(u<<1,x,v);
        else        modify(u<<1|1,x,v);
        pushup(u);
    }
}

node query(ll u,ll l,ll r)
{
    if(l<=tr[u].l&&tr[u].r<=r)  return tr[u];
    else
    {
        ll mid=tr[u].l+tr[u].r>>1;
        if(r<=mid)      return query(u<<1,l,r);//左边
        else if(l>mid)  return query(u<<1|1,l,r);//右边
        else
        {
            auto left=query(u<<1,l,r);
            auto right=query(u<<1|1,l,r);
            node res;
            pushup(res,left,right);
            return res;
        }
    }
}

int main()
{
    ll n,m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&s[i]);
        w[i]=s[i]-s[i-1];
    }
    build(1,1,n);
    while(m--)
    {
        char op[3];
        scanf("%s",op);
        if(op[0]=='C')//l~r 加上 d
        {
            ll l,r,d;
            scanf("%lld%lld%lld",&l,&r,&d);
            modify(1,l,d);
            if(r+1<=n)  modify(1,r+1,-d);
        }
        else//查询l~r的gcd. 
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            ll res1=query(1,1,l).sum;
            ll res2=query(1,l+1,r).d;
            printf("%lld\n",abs(__gcd(res1,res2)));
        }
    }
    return 0;
}