zoukankan      html  css  js  c++  java
  • seq 差分

    Description

    白云建立了n个商店,白兔打算按照编号1 . . . n的顺序访问这些商店。 商店i有一个
    价格a i 表示交易商品所需的代价。
    白兔在按顺序走时,每到达一个商店,可以花费代价购买一件商品,并放入自己手
    中。也可以出售手上的商品,并获得利润。
    白兔的力量有限,同一时刻只能携带一个商品。问它遍历完所有商店后能够获得的
    利润最大是多少?
    白兔的精力也有限,所以,在最大化利润的前提下,它想让交易次数尽可能地少。
    当然,白云不想让白兔轻松获利,它有时会命令一段区间内的商店把价格同时加上
    一个数。

    solution

    显然是找到许多个递增段,每一次该段的最大值减去最小值,我们可以线段树维护这个东西,但是有一个巧妙的差分思想:我们该原数组为差分数组后,问题就转化为求所有正数和,修改也变成了单点修改,第一问就做完了,第二问我们只需要特判一个 (0) 即可,我们维护正数区间的段,直接线段树合并时维护即可,我们发现如果0和一个正数接在一起,我们可以当做一段,这样就达到了第二问最小化购买的要求

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    
    #define RG register
    #define il inline
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    
    #define ls (node<<1)
    #define rs (node<<1|1)
    using namespace std;
    const int N=100005;
    typedef long long ll;
    int n,Q,a[N];
    ll tot=0;
    int tr[N<<2],fi[N<<2],suf[N<<2],sum[N<<2];
    
    il void upd(int node){
       tr[node]=tr[ls]+tr[rs]-(suf[ls]&sum[rs]);
       suf[node]=suf[rs]|(fi[rs]&suf[ls]);
       sum[node]=sum[ls]|(fi[ls]&sum[rs]);
       fi[node]=fi[ls]&fi[rs];
    }
    
    il void ins(int l,int r,int node,int sa){
       if(l==r){
          suf[node]=sum[node]=tr[node]=a[sa]>0,fi[node]=a[sa]==0;
          return ;
       }
       int mid=(l+r)>>1;
       if(sa<=mid)ins(l,mid,ls,sa);
       else ins(mid+1,r,rs,sa);
       upd(node);
    }
    
    il void build(int l,int r,int node){
       if(l==r){
          suf[node]=sum[node]=tr[node]=a[l]>0,fi[node]=a[l]==0;
          return ;
       }
       int mid=(l+r)>>1;
       build(l,mid,ls);build(mid+1,r,rs);
       upd(node);
    }
    
    void Clear(){
       int lim=N*4-1;
       for(RG int i=0;i<lim;i++)
          tr[i]=fi[i]=sum[i]=suf[i]=0;
       tot=0;
    }
    
    void work()
    {
       Clear();
       scanf("%d%d",&n,&Q);
       for(int i=1;i<=n;i++)scanf("%d",&a[i]);
       for(int i=n;i>=1;i--)a[i]-=a[i-1];
       a[1]=0;
       for(int i=2;i<=n;i++)tot+=Max(a[i],0);
    
       build(1,n,1);
       int flag,l,r,c;
       while(Q--){
          scanf("%d",&flag);
          if(!flag){
             scanf("%d%d%d",&l,&r,&c);
             if(l>1){
                tot-=Max(a[l],0);
                a[l]+=c;
                tot+=Max(a[l],0);
                ins(1,n,1,l);
             }
    
             if(r<n){
                tot-=Max(a[r+1],0);
                a[r+1]-=c;
                tot+=Max(a[r+1],0);
                ins(1,n,1,r+1);
             }
          }
          else printf("%lld %d
    ",tot,tr[1]<<1);
       }
    }
    
    int main(){
       int T;cin>>T;
       while(T--)work();
       return 0;
    }
    
    
  • 相关阅读:
    开发工具(四)
    开发工具(三)
    调试(二)
    调试(一)
    jsp乱码解决大全(转自csdn一高手)
    开发工具(二)
    开发工具
    在 SQL Server 2000 中对链接服务器运行分布式事务在您安装 Windows Server 2003 或 Windows XP Service Pack 2 时可能收到 7391 错误信息
    蓝桥杯试题
    How to lay pipelines
  • 原文地址:https://www.cnblogs.com/Hxymmm/p/7780270.html
Copyright © 2011-2022 走看看