zoukankan      html  css  js  c++  java
  • 牛客小白月赛16 H 小阳的贝壳 (差分+线段树)

    链接:https://ac.nowcoder.com/acm/contest/949/H
    来源:牛客网

    题目描述

    小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 colicoli 。现在小阳有 3 种操作:

    1 l r x:给 [l,r][l,r] 区间里所有贝壳的颜色值加上 xx 。

    2 l r:询问 [l,r][l,r] 区间里所有相邻贝壳 颜色值的差(取绝对值) 的最大值(若 l=rl=r 输出 0)。

    3 l r :询问 [l,r][l,r] 区间里所有贝壳颜色值的最大公约数。

    输入描述:

    第一行输入两个正整数 n,mn,m,分别表示贝壳个数和操作个数。
    第二行输入 nn 个数 colicoli,表示每个贝壳的初始颜色。
    第三到第 m+2m+2 行,每行第一个数为 optopt,表示操作编号。接下来的输入的变量与操作编号对应。

    输出描述:

    共 m 行,对于每个询问(操作 2 和操作 3)输出对应的结果。
    示例1

    输入

    5 6
    2 2 3 3 3
    1 2 3 3
    2 2 4
    3 3 5
    1 1 4 2
    3 2 3
    2 3 5

    输出

    3
    3
    1
    3

    备注:

    1n,m105,1coli,x103,1opt3,1lrn

    思路:
    因为gcd(a,b) == gcd(a,b-a),那么我们把原数组差分一下,这样区间修改就只用修改两个点了,求相邻两点的差值也是一样的,线段树上多维护个mx[]就好了

    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid ll m = (l + r) >> 1
    const ll M = 2e5+10;
    ll a[M],b[M],c[M],sum[M<<2],mx[M<<2],n;
    ll lowbit(ll x)
    {
        return x & -x;
    }
    void add(ll x,ll val){
        for(ll i = x;i <= M;i += lowbit(i)){
            c[i] += val;
        }
    }
    
    ll getsum(ll x){
        ll ans = 0;
        for(ll i = x;i > 0;i -= lowbit(i)){
            ans += c[i];
        }
        return ans;
    }
    
    void up(ll rt){
        sum[rt] = __gcd(sum[rt<<1] ,sum[rt<<1|1]);
        mx[rt] = max(abs(mx[rt<<1]),abs(mx[rt<<1|1]));
    }
    
    void build(ll l,ll r,ll rt){
        if(l == r){
            sum[rt] = b[l];
            mx[rt] = b[l];
            return ;
        }
        mid;
        build(lson); build(rson);
        up(rt);
    }
    
    void update(ll p,ll c,ll l,ll r,ll rt){
        if(l == r){
            sum[rt] += c;
            mx[rt] += c;
            return ;
        }
        mid;
        if(p <= m) update(p,c,lson);
        else update(p,c,rson);
        up(rt);
    }
    
    ll query_gcd(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        mid;
        ll ret = 0;
        if(L <= m) ret = __gcd(ret,query_gcd(L,R,lson));
        if(R > m) ret = __gcd(ret,query_gcd(L,R,rson));
        return abs(ret);
    }
    
    ll query_max(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return mx[rt];
        }
        mid;
        ll ret = 0;
        if(L <= m) ret = max(ret,abs(query_max(L,R,lson)));
        if(R > m) ret = max(ret,abs(query_max(L,R,rson)));
        return ret;
    }
    
    
    
    int main()
    {
        ll m,l,r,x;
        scanf("%lld%lld",&n,&m);
        for(ll i = 1;i <= n;i ++) scanf("%lld",&a[i]),b[i]=a[i]-a[i-1];
        build(1,n,1);
        ll op;
        for(ll i = 1;i <= m;i ++){
            scanf("%lld",&op);
            if(op == 1){
                scanf("%lld%lld%lld",&l,&r,&x);
                update(l,x,1,n,1);
                if(r < n) update(r+1,-x,1,n,1);
                add(l,x); add(r+1,-x);
            }
            else if(op == 2){
                scanf("%lld%lld",&l,&r);
                ll ans;
                if(l!=r)
                ans = query_max(l+1,r,1,n,1);
                else
                ans = 0;
                printf("%lld
    ",ans);
            }
            else {
                scanf("%lld%lld",&l,&r);
                ll cnt = a[l] + getsum(l);
                if(l != r){
                ll ans = query_gcd(l+1,r,1,n,1);
                printf("%lld
    ",__gcd(cnt,ans));
                }
                else {
                    printf("%lld
    ",cnt);
                }
            }
        }
        return 0;
    }
     
  • 相关阅读:
    LeetCode 204
    华为OJ2051-最小的K个数(Top K问题)
    华为OJ1964-求解立方根(牛顿迭代法)
    华为OJ2288-合唱队(最长递增子序列)
    华为OJ2011-最长公共子串
    【Unix编程】进程间通信(IPC)
    可利用空间表(Free List)
    13.10 Scrapy 通用爬虫
    13.9 Scrapy 对接 Splash
    第十四章 分布式爬虫
  • 原文地址:https://www.cnblogs.com/kls123/p/11178600.html
Copyright © 2011-2022 走看看