Interval GCD CH4302
##題目大意:長さNの数列AとM個の指令(N≦5*10^5,M<=10^5)を与えて、各指令は以下の2種類の1つである可能性がある:“C l r d”、A[l],A[l+1],...,A[r]をすべてdを加えることを表す.「Q l r」は、A[l],A[l+1],...,A[r]に問い合わせる最大公約数(GCD)を表す
##解題構想:線分樹+GCD=正解GCD更相減損術|(拡張)ユークリッドアルゴリズムはすべてユークリッドアルゴリズムが通過することができて、私はユークリッドを使ってgcd t[now]を求めた.g=gcd(t[leftson].g,t[rightson].g); 質問の答えはgcd(a[l],Ask(1,l+1,r))である.
私は多くの人の書き方が私と違うことに気づいたので、他の人の書き方を使ってみました.それから私は心の中で黙々と思っています:もう他の人の書き方を使わないで、もともと直したいと思っていましたが、私は怠け者で、私はあまり直す时間がありません.どうせACができるのは良いコードです.
##Accepted code:
##解題構想:線分樹+GCD=正解GCD更相減損術|(拡張)ユークリッドアルゴリズムはすべてユークリッドアルゴリズムが通過することができて、私はユークリッドを使ってgcd t[now]を求めた.g=gcd(t[leftson].g,t[rightson].g); 質問の答えはgcd(a[l],Ask(1,l+1,r))である.
私は多くの人の書き方が私と違うことに気づいたので、他の人の書き方を使ってみました.それから私は心の中で黙々と思っています:もう他の人の書き方を使わないで、もともと直したいと思っていましたが、私は怠け者で、私はあまり直す时間がありません.どうせACができるのは良いコードです.
##Accepted code:
#include
#include
#include
#define ls (now<<1)
#define rs ((now<<1)+1)
#define ll long long
using namespace std;
const int N=5e5+5;
const int M=1e5+5;
ll a[N],b[N],num[N<<2],s[N<<2];
int l[N<<2],r[N<<2],lc[N<<2],rc[N<<2],n,m;
//
inline void read(ll &f) {
char c=getchar();f=0;int ag=1;
while(!isdigit(c)) {if (c=='-') ag=-1; c=getchar();}
while(isdigit(c)){f=(f<<3)+(f<<1)+c-48;c=getchar();}
f*=ag; return;
}
void write(ll x) {
if(x>9) write(x/10);putchar(x%10+48);return;
}
void writeln(ll x) {
if (x<0) putchar('-'),x*=-1; write(x); putchar('
'); return;
}
//
//
void add(int x,ll y) {
for(;x<=n;x+=(x&-x)) s[x]+=y;
}
ll get(int x) {
ll res=0;
for(;x;x-=(x&-x)) res+=s[x];
return res;
}
//
// GCD
ll gcd(ll a,ll b)
{
return !a?b:gcd(b%a,a);
}
// GCD
//
//
int len=0;
void build(int L,int R)
{
int t=++len;
l[t]=L;r[t]=R;
if(L==R){num[t]=b[L];return;}
int mid=(L+R)>>1;
lc[t]=len+1,build(L,mid);
rc[t]=len+1,build(mid+1,R);
num[t]=gcd(num[lc[t]],num[rc[t]]);
}
//
void change(int now,int x,ll dat) {
if (l[now]==r[now]) {num[now]+=dat;return;}
int mid=(l[now]+r[now])>>1;
if (x<=mid) change(lc[now],x,dat);
else change(rc[now],x,dat);
num[now]=gcd(num[lc[now]],num[rc[now]]);
}
//
ll Ask(int now,int x,int y) {
if (x>y) return 1;
if (l[now]==x&&r[now]==y) return num[now];
int mid=(l[now]+r[now])>>1;
if (y<=mid) return Ask(lc[now],x,y);
else if (x>mid) return Ask(rc[now],x,y);
else
return gcd(Ask(lc[now],x,mid)
,Ask(rc[now],mid+1,y));
}
//
int main() {
// freopen("input","r",stdin);
// freopen("1.txt","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) read(a[i]);
for (int i=1;i<=n;i++) b[i]=a[i+1]-a[i];
add(1,a[1]);
for (int i=2;i<=n;i++) add(i,b[i-1]);
build(1,n-1);
while(m--)
{
char c[2];
scanf("%s",c);
int l,r;
scanf("%d%d",&l,&r);
if(c[0]=='Q')
writeln(abs(gcd(get(l),Ask(1,l,r-1))));
else
{
ll dat; read(dat);
add(l,dat);
if(l>1)change(1,l-1,dat);
if(r