牛客小白月赛16 H、小阳的贝壳

对原序列进行差分,得到新的序列。
维护这个序列的最大值, gcd \gcd
对于区间 [ l , r ] [l,r] gcd \gcd ,只需要求 gcd ( a [ l ] , gcd ( a [ l + 1 ] , . . . a [ r ] ) ) \gcd(a[l],\gcd(a[l+1],...a[r]))
因为 gcd ( a , b , c ) = gcd ( a , b a , c a ) \gcd(a,b,c) = \gcd(a,b-a,c-a) ,更相减损法。
a [ l ] a[l] 是已经修改之后的值,

code

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
ll a[man],b[man];
ll maxx[man<<2],g[man<<2];
  
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
void pushup(int rt){
    maxx[rt] = max(abs(maxx[rt<<1]),abs(maxx[rt<<1|1]));
    g[rt] = gcd(g[rt<<1],g[rt<<1|1]);
}
  
void build(int l,int r,int rt){
    if(l==r){
        g[rt] =  b[l];
        maxx[rt] = b[l];
        return;
    }
    int m = l + r >> 1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
  
void update(int l,int r,int pos,int rt,ll va){
    if(l==r){
        maxx[rt] += va;
        g[rt] = maxx[rt];
        return;
    }
    int m = l +r >>1;
    if(pos<=m)update(l,m,pos,rt<<1,va);
    else update(m+1,r,pos,rt<<1|1,va);
    pushup(rt);
}
  
ll query_max(int l,int r,int L,int R,int rt){
    if(L<=l&&R>=r){
        return abs(maxx[rt]);
    }
    int m = l + r >> 1;
    ll ans1 = 0,ans2 = 0;
    if(L<=m)ans1 = query_max(l,m,L,R,rt<<1);
    if(R>m)ans2 = query_max(m+1,r,L,R,rt<<1|1);
    return max(ans1,ans2);
}
  
ll query_gcd(int l,int r,int L,int R,int rt){
    if(L<=l&&R>=r){
        return g[rt];
    }
    int m = l + r >> 1;
    ll ans1 = 0,ans2 = 0;
    if(L<=m)ans1 = query_gcd(l,m,L,R,rt<<1);
    if(R>m)ans2 = query_gcd(m+1,r,L,R,rt<<1|1);
    return gcd(ans1,ans2);
}
  
ll c[man];int n,m;
#define lowbit(x) x&(-x)
void add(int pos,int x){
    for(int i = pos;i <= n+5;i +=lowbit(i))c[i] += x;
}
ll query(int pos){
    ll ans = 0;
    for(int i = pos;i >= 1;i -= lowbit(i)){
        ans += c[i];
    }
    return ans;
}
  
signed main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i){
        scanf("%lld",a+i);
        c[i] = 0;
        b[i] = a[i] - a[i-1];
    }
    build(1,n+5,1);
    while(m--){
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(1==op){
            ll x;scanf("%lld",&x);
            add(l,x);add(r+1,-x);
            update(1,n+5,l,1,x);
            update(1,n+5,r+1,1,-x);
        }else if(2==op){
            if(l==r)printf("%d\n",0);
            else printf("%lld\n",query_max(1,n+5,l+1,r,1));
        }else{
            ll x = a[l] + query(l);
            //cout << "x :" <<x <<endl;
            if(l==r)printf("%lld\n",x);
            else printf("%lld\n",gcd(x,abs(query_gcd(1,n+5,l+1,r,1))));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/107279482