思路:求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;
}
京公网安备 11010502036488号