Z bzoj 5028 fueling small shop (D11 sequence GCD) (Fenwick tree segment tree +)

The meaning of problems

Given a sequence of two operations, one is seeking gcd interval period, the other is to add a value interval period. (See it is as to why the interval gcd, that Italy should be in the range inside the bottle shuffling back and forth, and finally you want a bottle of oil to the customer, then according to Theorem Shu Pei what can know )

answer

According to known technique Decreases gcd (x, y) = gcd (x, yx), then readily available for the three numbers gcd (x, y, z) = gcd (x, yx, zy);

Easy to use mathematical induction to prove any integer multiple of the nature of the heap are established

The above formula is not like there is a difference?

Therefore, we can use the difference to modify the interval into two modified single point, when modifying only know a [l] and [l + 1, r] can gcd this difference interval.

For differential arrays we can build segment tree maintenance intervals gcd, for the value of a single point of maintenance can be used Fenwick tree.

Note that the query, if l == r gives directly a [l] to a value, or the determination of the segment tree Laid query returns 0, take folk abs

Modifying if r == n r + 1 is not to change the

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,root,num;
int a[maxn],b[maxn];
int ls[maxn<<1],rs[maxn<<1],gcd[maxn<<1];
int cx[maxn];

template<class T>inline void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

int get_gcd(int a,int b){
    return !b ? a : get_gcd(b,a%b);
}

void update(int rt){
    gcd[rt]=get_gcd(gcd[ls[rt]],gcd[rs[rt]]);
}

void build(int &rt,int l,int r){
    if(!rt) rt=++num;
    if(l==r) {gcd[rt]=a[l];return ;}
    int mid=(l+r)>>1;
    build(ls[rt],l,mid);
    build(rs[rt],mid+1,r);
    update(rt);
}

void add(int x,int val){for(;x<=n;x+=x&-x) cx[x]+=val;}

int sum(int x){
    int ret=0;
    for(;x;x-=x&-x)
     ret+=cx[x];
    return ret;
}

int query(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R) return gcd[rt];
    int mid=(l+r)>>1;
    if(R<=mid) return query(ls[rt],l,mid,L,R);
    if(mid<L) return query(rs[rt],mid+1,r,L,R);
    return get_gcd(query(ls[rt],l,mid,L,R),query(rs[rt],mid+1,r,L,R));
}

void modify(int rt,int l,int r,int pos,int val){
    if(l==r){
        gcd[rt]+=val;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) modify(ls[rt],l,mid,pos,val);
    else modify(rs[rt],mid+1,r,pos,val);
    update(rt);
}

int main(){
    read(n);read(m);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=n;i;i--) a[i]-=a[i-1],add(i,a[i]);
    build(root,1,n);
    for(int i=1;i<=m;i++){
        int op,l,r;
        read(op);read(l);read(r);
        if(l>r) swap(l,r);
        if(op==1){
            if(l==r) printf("%d\n",sum(l));
            else printf("%d\n",abs(get_gcd(sum(l),query(root,1,n,l+1,r))));
        }
        else {
            int v;
            read(v);
            add(l,v);add(r+1,-v);
            modify(root,1,n,l,v);
            if(r<n) modify(root,1,n,r+1,-v);
        }
    }
}
View Code

 

Guess you like

Origin www.cnblogs.com/sto324/p/11240530.html