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的正整数。

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
",ans);
        }
    }
    return 0;
}

  

 

  

原文地址:https://www.cnblogs.com/Accpted/p/11311573.html