zoukankan      html  css  js  c++  java
  • 区间最大公约数

    题目链接

    题意:给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

       1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

       2、“Q l r”,表示询问 A[l],A[l+1],…,A[r] 的最大公约数(GCD)。

       对于每个询问,输出一个整数表示答案。

    思路:因为更相减损数gcd(x,y)=gcd(x,y-x),而且正负不影响,所以可以维护A[i]数组的差分的线段树。当进行操作C时,既把A[l]加d,把A[r+1]减d。

    然后当进行Q操作时,因为C操作的改变,所以就把[l+1,r]的线段树值求出来,与A[l]进行gcd。求A[l]就可以维护一个树状数组的区间操作,就能够得

    到A[i]的值,即可求出答案。注意这题long long。

    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define lowbit(x) x&(-x)
    using namespace std;
    const int N=5e5+100;
    struct point 
    {
        ll l;
        ll r;
        ll dat;
    }t[N*4];
    ll a[N],c[N],b[N];
    ll n,m;
    void build(int p,ll l,ll r)
    {
        t[p].l=l;
        t[p].r=r;
        if(l==r)
        {
            t[p].dat=c[l];
            return;
        }
        ll mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p*2+1,mid+1,r);
        t[p].dat=__gcd(t[p<<1].dat,t[p*2+1].dat);
    }
    void update(int p,ll x,ll v)
    {
        if(x>n)
        return;
        if(t[p].l==t[p].r)
        {
            t[p].dat=t[p].dat+v;
            return;
        }
        ll mid=(t[p].l+t[p].r)>>1;
        if(mid>=x)
        {
            update(p<<1,x,v);
        }
        else
        update(p*2+1,x,v);
        t[p].dat=__gcd(t[p<<1].dat,t[p*2+1].dat);
    }
    ll ask(int p,ll l,ll r)
    {
        if(l>r)
        return 0;
        if(t[p].l>=l&&t[p].r<=r)
        {
            return abs(t[p].dat);
        }
        ll mid=(t[p].l+t[p].r)>>1;
        ll vl=0,vr=0; 
        if(mid>=l)
        {
            vl=ask(p<<1,l,r);
        }
        if(mid<r)
        {
            vr=ask(p*2+1,l,r);
        }
        return abs(__gcd(vl,vr));
    }
    void add(ll x,ll v)
    {
        for(;x<=n;x+=lowbit(x))
        {
            b[x]+=v;
        }
    }
    ll query(ll x)
    {
        ll ans=0;
        for(;x;x-=lowbit(x))
        {
            ans+=b[x];
        }
        return ans;
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            c[i]=a[i]-a[i-1]; 
        }
        build(1,1,n);
        char s[5];
        ll x,y,z;
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='Q')
            {
                scanf("%lld%lld",&x,&y);
                //printf("aa:%lld
    ",query(x)+a[x]);
            //    printf("%lld
    ",ask(1,x+1,y));
                printf("%lld
    ",__gcd(a[x]+query(x),ask(1,x+1,y)));
            }
            else
            {
                scanf("%lld%lld%lld",&x,&y,&z);
                update(1,x,z);
                update(1,y+1,-z);
                add(x,z);
                add(y+1,-z);
            }
        }
    }
  • 相关阅读:
    Selenium WebDriver 中鼠标和键盘事件分析及扩展
    Windows Mobile 常用键值VK对应表
    application.yml
    示例
    秒懂HTTPS接口(实现篇)
    秒懂HTTPS接口(接口测试篇)
    秒懂HTTPS接口(原理篇)
    SpringBoot全局捕获异常示例
    官方文档
    Python基础02——控制流
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/11359868.html
Copyright © 2011-2022 走看看