题目链接:区间最大公约数
题解
本题有两个操作给区间加上一个数以及查询区间gcd(最大公约数)。
查询按照线段树查询模板操作即可。难点在于区间修改。单纯的暴力每次修改O(nlogn),显然比直接暴力还暴力,定会超时。
遇到这种给区间加上一个数的一般可想到差分思想
刚好由夹逼准则不难证明一个等式:
g
c
d
(
a
1
,
a
2
,
.
.
.
,
a
n
)
=
g
c
d
(
a
1
,
a
2
−
a
1
,
.
.
.
a
n
−
a
n
−
1
)
{gcd(a_1,a_2,...,a_n)=gcd(a_1,a_2-a_1,...a_n-a_{n-1})}
gcd(a1,a2,...,an)=gcd(a1,a2−a1,...an−an−1)
显然我们维护一个差分和一个gcd的线段树就能解决问题。
假设 b i = a i − a i − 1 {b_i=a_i-a_{i-1}} bi=ai−ai−1
- 区间[l,r]求gcd时,可通过 g c d ( ∑ i = 1 l b i , g c d ( b l + 1 , . . . . , b r ) ) {gcd(\sum_{i=1}^{l}b_i,gcd(b_{l+1,....,b_r}))} gcd(∑i=1lbi,gcd(bl+1,....,br))求得
- 区间修改时,按照差分的思想只需单点更改add(l,d)和add(r+1,-d)即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
struct Tr
{
ll sum,gcd;
Tr(ll _sum=0,ll _gcd=0)
{
sum=_sum;
gcd=_gcd;
}
}tr[N<<2];
ll addv[N<<2],a[N];
inline ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }
void pushup(int p,int l,int r)
{
tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
tr[p].gcd=gcd(tr[p<<1].gcd,tr[p<<1|1].gcd);
}
void build(int p,int l,int r)
{
if(l==r)
{
tr[p].gcd=tr[p].sum=a[l]-a[l-1];
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p,l,r);
}
void add(int p,int l,int r,int pos,ll v)
{
if(l==r)
{
tr[p].sum+=v;
tr[p].gcd+=v;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) add(p<<1,l,mid,pos,v);
else add(p<<1|1,mid+1,r,pos,v);
pushup(p,l,r);
}
Tr query(int p,int l,int r,int ql,int qr)
{
Tr res=Tr(0,0);
if(ql>qr) return res;
if(ql<=l && qr>=r) return tr[p];
int mid=(l+r)>>1;
if(ql<=mid) res=query(p<<1,l,mid,ql,qr);
if(qr>mid)
{
Tr tp=query(p<<1|1,mid+1,r,ql,qr);
res.gcd=gcd(res.gcd,tp.gcd);
res.sum+=tp.sum;
}
pushup(p,l,r);
return res;
}
int main()
{
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
char op[2]; scanf("%s",op);
if(op[0]=='Q')
{
int l,r; scanf("%d%d",&l,&r);
Tr tp1=query(1,1,n,1,l),tp2=query(1,1,n,l+1,r);
printf("%lld\n",abs(gcd(tp1.sum,tp2.gcd)));
}
else
{
int l,r; ll d; scanf("%d%d%lld",&l,&r,&d);
add(1,1,n,l,d);
if(r+1<=n) add(1,1,n,r+1,-d);
}
}
}
/*
5 5
1 3 5 7 9
C 1 5 1
C 3 3 6
*/