• [Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]


    咸鱼了好久...出来冒个泡_(:з」∠)_

    题目连接:1107G - Vasya and Maximum Profit

    题目大意:给出(n,a)以及长度为(n)的数组(c_i)和长度为(n)的严格单调上升数组(d_i),求(maxlimits_{1 le l le r le n} (acdot(r-l+1)-sum_{i=l}^{r}c_i-gap(l,r))),其中(gap(l, r) = maxlimits_{l le i < r} (d_{i + 1} - d_i)^2)

    题解:首先将所有的(c_i)转换为(a-c_i),这样就变成了求(maxlimits_{1 le l le r le n} (sum_{i=l}^{r}c_i-gap(l,r)))。如果(l,r)确定的话,我们就能通过求前缀和以及区间内最大值来算出该区间对应的答案,但我们还需要进一步的优化。

      考虑每一个(d_{i + 1} - d_i)能成为(gap(l,r))的范围,即在区间([L,R])中,(forall L le l le r le R,gap(l,r)le d_{i + 1} - d_i)。这样我们只需要用线段树查询区间([L,R])的最大子段和就能求出当(gap(l,r) le d_{i + 1} - d_i)时的答案。先预处理所有的(L,R),再扫一遍就好了。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 300001
    #define LL long long
    LL n,b,l[N],r[N],a[N],d[N],L,R,M,S,ans;
    struct rua{LL l,r,w,s,lw,rw;}t[N<<2];
    void up(int x,int mid)
    {
        t[x].s=t[x*2].s+t[x*2+1].s;
        t[x].w=max(t[x*2].w,t[x*2+1].w);
        t[x].lw=max(t[x*2].lw,t[x*2].s+t[x*2+1].lw);
        t[x].rw=max(t[x*2+1].rw,t[x*2+1].s+t[x*2].rw);
        t[x].w=max(t[x].w,t[x*2].rw+t[x*2+1].lw);
    }
    void Build(int l,int r,int x)
    {
        t[x].l=l,t[x].r=r;
        if(l==r){t[x].w=t[x].lw=t[x].rw=t[x].s=a[l];return;}
        int mid=l+r>>1;
        Build(l,mid,x*2);
        Build(mid+1,r,x*2+1);
        up(x,mid);
    }
    void ask(int ll,int rr,int l,int r,int x)
    {
        if(ll>r || l>rr)return;
        int mid=l+r>>1;
        if(ll<=l && r<=rr)
          {
          M=max(M,max(t[x].w,R+t[x].lw));
          L=max(L,S+t[x].lw);
          R=max(R+t[x].s,t[x].rw);
          M=max(M,max(L,R));
          S+=t[x].s;
          return;
          }
        ask(ll,rr,l,mid,x*2);
        ask(ll,rr,mid+1,r,x*2+1);
    }
    int main()
    {
        scanf("%I64d%I64d",&n,&b);
        for(LL i=1;i<=n;i++)
          {
          scanf("%I64d%I64d",&d[i],&a[i]);
          a[i]=b-a[i],ans=max(ans,a[i]);
          }
        for(LL i=n;i>=1;i--)d[i]-=d[i-1];
        Build(1,n,1);
        d[1]=0;
        l[2]=2,r[n]=n;
        for(LL i=3;i<=n;i++)
          {
          LL _=i;
          while(_>2 && d[i]>=d[_-1])
            _=l[_-1];
          l[i]=_;
          }
        for(LL i=n-1;i>=2;i--)
          {
          LL _=i;
          while(_<n && d[i]>=d[_+1])
            _=r[_+1];
          r[i]=_;
          }
        for(LL i=2;i<=n;i++)
          {
          S=0;
          L=R=M=-(1e18);
          ask(l[i]-1,r[i],1,n,1);
          ans=max(ans,M-d[i]*d[i]);
          }
        printf("%I64d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    angularjs学习笔记一之显示数据,修改数据
    收藏/不再提醒
    CSS3动画
    Content-Type
    键盘快捷键
    url、href、src 详解
    关于docnment.write() 会清空原来的内容
    jq事件注意点
    echart的自适应
    键盘事件
  • 原文地址:https://www.cnblogs.com/DeaphetS/p/10326785.html
Copyright © 2020-2023  润新知