题目链接:https://ac.nowcoder.com/acm/contest/1033/B
再次吐槽CH
区间gcd再加区间修改。
一般求gcd的时候辗转相除法。
gcd(x,y)=gcd(x,y-x)
那么可以把这个公式推到3个项。
gcd(x,y,z)=gcd(x,y-x,z-y)
可以看出来这是一个差分数列。
原数列为a[],差分数列为b[]。
这样就可以用线段树在b[]上单点修改,l加上d,r+1减去d。
再用树状数组维护出一个c[]数组,区间修改,单点查询a[]数组。
这样的话答案就是
gcd(a[l]+aks_c(l),ask_t(1,1,n,l+1,r))
就可以较小复杂度处理了。
代码如下:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=500001; int n,m; ll c[maxn],a[maxn],b[maxn]; struct node{ ll ans; #define ans(x) t[x].ans }t[maxn<<2]; inline ll gcd(ll x,ll y){ return y ? gcd(y,x%y) : x; } inline void build(int p,int l,