Interval GCD

題目描述

給定一個長度爲N的數列A,以及M條指令 (N≤5*10^5, M<=10^5),每條指令多是如下兩種之一:
「C l r d」,表示把 A[l],A[l+1],…,A[r] 都加上 d。
「Q l r」,表示詢問 A[l],A[l+1],…,A[r] 的最大公約數(GCD)

輸入

第一行兩個整數N,M,第二行N個整數Ai,接下來M行每條指令的格式如題目描述所示。

輸出

對於每一個詢問,輸出一個整數表示答案。

樣例輸入

5 5
1 3 5 7 9
Q 1 5
C 1 5 1
Q 1 5
C 3 3 6
Q 2 4

樣例輸出

1
2
4

提示

N,M≤2*10^5,l<=r,數據保證任什麼時候刻序列中的數都是不超過2^62-1的正整數。c++

 

gcd(x,y)=gcd(x,y-x),gcd(x,y,z)=gcd(x,y-x,z-y)……對任意多個整數都成 將A數列進行查分,線段樹維護差分序列的最大公約數,每次詢問就是gcd(A[l],query(1,1,n,l+1,r); 每次修改update(1,1,n,l,d),update(1,1,n,r+1,-d) A數組也須要維護,線段樹和樹狀數組都行
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn=500200;
char s[10];
ll a[maxn],b[maxn],B[maxn*4],n,m,A[maxn*4];
void build (int rt,int l,int r)
{
    if (l==r)
    {
        B[rt]=b[l];
        return;
    }
    int mid=(l+r)>>1;
    build (rt<<1,l,mid);
    build (rt<<1|1,mid+1,r);
    B[rt]=__gcd(B[rt<<1],B[rt<<1|1]);
}

void update(int rt,int l,int r,int pos,ll val)
{
    if (l==r)
    {
        B[rt]+=val;
        return;
    }
    int mid=(l+r)>>1;
    if (pos<=mid)
    {
        update(rt<<1,l,mid,pos,val);
    }
    else
    {
        update(rt<<1|1,mid+1,r,pos,val);
    }
    B[rt]=__gcd(B[rt<<1],B[rt<<1|1]);
}

ll query(int rt,int l,int r,int L,int R)
{
    if (L<=l&&r<=R)
    {
        return B[rt];
    }
    int mid=(l+r)>>1;
    if (R<=mid)
    {
        return query(rt<<1,l,mid,L,R);
    }
    else
    {
        if (L>mid)
        {
            return query(rt<<1|1,mid+1,r,L,R);
        }
        else
        {
            return __gcd(query(rt<<1|1,mid+1,r,L,R),query(rt<<1,l,mid,L,R));
        }
    }
}
int lowbit(int x)
{
    return x&-x;
}

void add(int x,ll val)
{
    for (int i=x; i<=n; i+=lowbit(i))
    {
        A[i]+=val;
    }
}
ll sum(int x)
{
    ll res=0;
    for (int i=x; i; i-=lowbit(i))
    {
        res+=A[i];
    }
    return res;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for (int i=1; i<=n; i++)
    {
        scanf("%lld",&a[i]);
        b[i]=a[i]-a[i-1];
        add(i,b[i]);
    }
    build (1,1,n);
    while (m--)
    {
        ll l,r,d;
        scanf("%s",s);
        if (s[0]=='C')
        {

            scanf("%lld%lld%lld",&l,&r,&d);
            update(1,1,n,l,d);
            add(l,d);
            add(r+1,-d);
            if (r+1<=n) update(1,1,n,r+1,-d);
        }
        else
        {
            scanf("%lld%lld",&l,&r);
            ll ans=abs(__gcd(sum(l),query(1,1,n,l+1,r)));
            printf("%lld\n",ans);
        }
    }
    return 0;
}
相關文章
相關標籤/搜索