[BZOJ5028]小Z的加油店

[BZOJ5028]小Z的加油店

题目大意:

一个长度为\(n(n\le10^5)\)的数列,\(m(m\le10^5)\)次操作,支持区间加和区间\(\gcd\)

思路:

线段树维护差分,\(\gcd(A_l,\cdots,A_r)\)就是区间\([l,r]\)差分的\(\gcd\)\(A_r\)\(\gcd\)

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=1e5+1;
int a[N];
class SegmentTree {
    #define _left <<1
    #define _right <<1|1
    #define mid ((b+e)>>1)
    private:
        int gcd[N<<2],sum[N<<2];
        void push_up(const int &p) {
            gcd[p]=std::__gcd(gcd[p _left],gcd[p _right]);
            sum[p]=sum[p _left]+sum[p _right];
        }
    public:
        void build(const int &p,const int &b,const int &e) {
            if(b==e) {
                gcd[p]=sum[p]=a[b];
                return;
            }
            build(p _left,b,mid);
            build(p _right,mid+1,e);
            push_up(p);
        }
        void modify(const int &p,const int &b,const int &e,const int &x,const int &y) {
            if(b==e) {
                gcd[p]+=y;
                sum[p]+=y;
                return;
            }
            if(x<=mid) modify(p _left,b,mid,x,y);
            if(x>mid) modify(p _right,mid+1,e,x,y);
            push_up(p);
        }
        int query_gcd(const int &p,const int &b,const int &e,const int &l,const int &r) const {
            if(b==l&&e==r) return gcd[p];
            if(r<=mid) return query_gcd(p _left,b,mid,l,r);
            if(l>mid) return query_gcd(p _right,mid+1,e,l,r);
            return std::__gcd(query_gcd(p _left,b,mid,l,mid),query_gcd(p _right,mid+1,e,mid+1,r));
        }
        int query_sum(const int &p,const int &b,const int &e,const int &x) const {
            if(e==x) return sum[p];
            if(x<=mid) return query_sum(p _left,b,mid,x);
            if(x>mid) return sum[p _left]+query_sum(p _right,mid+1,e,x);
        }
    #undef _left
    #undef _right
    #undef mid
};
SegmentTree t;
int main() {
    const int n=getint(),m=getint();
    for(register int i=1;i<=n;i++) a[i]=getint();
    for(register int i=n;i>=1;i--) a[i]-=a[i-1];
    t.build(1,1,n);
    for(register int i=0;i<m;i++) {
        const int opt=getint(),l=getint(),r=getint();
        if(opt==1) {
            if(l<r) {
                printf("%d\n",std::abs(std::__gcd(t.query_sum(1,1,n,r),t.query_gcd(1,1,n,l+1,r))));
            } else {
                printf("%d\n",t.query_sum(1,1,n,r));
            }
        } else {
            const int v=getint();
            t.modify(1,1,n,l,v);
            if(r<n) t.modify(1,1,n,r+1,-v);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/skylee03/p/9346311.html
今日推荐