• NC26255小阳的贝壳(线段树+区间维护gcd+差分数组)


    链接:https://ac.nowcoder.com/acm/problem/26255
    来源:牛客网

    题目描述

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

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

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

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

    输入描述:

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

    输出描述:

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

    思路

    题目是关于区间修改和区间查询的,考虑线段树或者树状数组,舍去树状数组。

    如何用线段树去写?如果只是维护原数组的话肯定是没办法解决问题的。

    所以用线段树去维护差分数组(d[])

    对于操作1,对应于差分数组的(d[l]+x,d[r+1]-x)操作。因此考虑用线段树进行单点修改。

    对于操作2,求的是区间([l,r])(|t_i-t_{i-1}|(l+1)leq ileq j)的最大值,也就是差分数组的(d[i])的最大值。因子考虑用线段树维护(|d[i]|)的最大值

    对于操作3,

    [gcd(t_l,t_{l+1},t_{l+2},…,t_{r})=gcd(t_l,|t_{l+1}-t_l|,…,|t_{r}-t_{r-1}|) ]

    [=gcd(t_l,|d_{l+1}|,|d_{l+2}|,…,|d_r|) ]

    [=gcd(sum_{i=1}^{l}d_i,|d_{l+1}|,…,|d_r|) ]

    因此考虑用线段树维护区间内(|d_i|)的最小公倍数和其区间和。

    综上所述,线段树节点包含的信息有,区间内(d_i)的和、区间内(|d_i|)的最大公约数、区间内(d_i)的值。

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define DOF 0x7f7f7f7f
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a))
    #define debug(case,x); cout<<case<<"  : "<<x<<endl;
    #define open freopen("ii.txt","r",stdin)
    #define close freopen("oo.txt","w",stdout)
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pb push_back
    using namespace std;
    #define int long long
    #define lson rt<<1
    #define rson rt<<1|1
    const int maxn=1e5+10;
    
    int t[maxn],d[maxn];
    
    struct tree{
        int l,r;
        int sum,maxx,gcd;
    }tree[maxn<<2];
    
    void push_up(int rt){
        tree[rt].sum=tree[lson].sum+tree[rson].sum;
        tree[rt].gcd=__gcd(tree[lson].gcd,tree[rson].gcd);
        tree[rt].maxx=max(tree[lson].maxx,tree[rson].maxx);
    }
    
    
    void build(int rt,int l,int r){
        tree[rt].l=l,tree[rt].r=r;
        if(l==r){
            tree[rt].maxx=tree[rt].gcd=abs(d[l]);
            tree[rt].sum=d[l];
            return ;
        }
    
        int mid=(l+r)>>1;
    
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(rt);
    
    }
    
    void update_point(int rt,int x,int k){
        if(tree[rt].l==x&&tree[rt].r==x){
            tree[rt].sum+=k;
            tree[rt].maxx=tree[rt].gcd=abs(tree[rt].sum);
            return ;
        }
    
        int mid=(tree[rt].r+tree[rt].l)>>1;
    
        if(x<=mid)update_point(lson,x,k);
        else update_point(rson,x,k);
    
        push_up(rt);
    
    }
    
    int query_sum(int rt,int l,int r){
        if(tree[rt].l>=l&&tree[rt].r<=r){
            return tree[rt].sum;
        }
        
    
        int mid=(tree[rt].l+tree[rt].r)>>1;
        int res=0;
    
        if(l<=mid){
            res+=query_sum(lson,l,r);
        }
        if(r>mid){
            res+=query_sum(rson,l,r);
        }
        return res;
    
    }
    
    
    int query_gcd(int rt,int l,int r){
        if(l<=tree[rt].l&&tree[rt].r<=r)
            return tree[rt].gcd;
    
        int mid=(tree[rt].l+tree[rt].r)>>1;
        int res=0;
    
        if(l<=mid) res=__gcd(res,query_gcd(lson,l,r));
        if(r>mid) res=__gcd(res,query_gcd(rson,l,r));
        return res;
    
    }
    
    int query_max(int rt,int l,int r){
        if(tree[rt].l>=l&&tree[rt].r<=r)
            return tree[rt].maxx;
        int mid=(tree[rt].l+tree[rt].r)>>1;
        int res=0;
    
        if(l<=mid) res=max(res,query_max(lson,l,r));
        if(r>mid) res=max(res,query_max(rson,l,r));
    
        return res;
    
    }
    
    
    signed main(){
        int n,m;scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%lld",&t[i]);
            d[i]=t[i]-t[i-1];
        }
        build(1,1,n);
        while(m--){
            int op,l,r;scanf("%lld%lld%lld",&op,&l,&r);
            if(op==1){
                int x;scanf("%lld",&x);
                update_point(1,l,x);
                if(r<n) update_point(1,r+1,-x);
            }else if(op==2){
                if(l==r)printf("0
    ");
                else printf("%lld
    ",query_max(1,l+1,r));
            }else{
                printf("%lld
    ",__gcd(query_sum(1,1,l),query_gcd(1,l+1,r)));
            }
        }
    
    
    
    }
    
  • 相关阅读:
    Python爬虫之编写一个可复用的下载模块
    Python爬虫之BeautifulSoup的用法
    解决:Python爬取https站点时SNIMissingWarning和InsecurePlatformWarning
    解决:xampp中Apache, MySql, Filezilla端口占用问题
    Python中的Unicode编码和UTF-8编码
    解决:AttributeError: module 'requests' has no attribute 'get'”
    解决:return _compile(pattern, flags).search(string) TypeError: expected string or buffer
    NOIP 2014 提高组 Day1
    NOIP2013 提高组 Day2
    poj 3020 Antenna Placement
  • 原文地址:https://www.cnblogs.com/waryan/p/13357196.html
Copyright © 2020-2023  润新知