zoukankan      html  css  js  c++  java
  • 题解 CF1107G 【Vasya and Maximum Profit】

    推销 膜 zhouakngyang 宝典

    (color{black}{ exttt {z}}color{red}{ exttt {houakngyang}}) AK 完比赛让我来做这题。

    题解:

    为了方便,直接把 (d_i) 设为输入的 ((d_{i+1}-d_i)^2)

    直接做看不出啥我太菜了 ,只好先表示答案

    [ ans=max{a imes (r-l+1) -sum_{i=l}^{r}c_i-max_{i=l}^{r-1}{d_i} } ]

    请注意 (max_{i=l}^{r-1}{d_i})(r-1)

    显然的加一个前缀和,设 (sc_i=sumlimits_{j=1}^{i}c_j)

    [ans=max{a imes (r-l+1) -sc_{r}-sc_{l-1}-max_{i=l}^{r-1}{d_i} } ]

    然后就自闭了 (5min)

    无聊变换一下式子,

    [ans=max{(a imes r -sc_r)-(a imes (l-1)-sc_{l-1})-max_{i=l}^{r-1}{d_i} } ]

    发现除了那个 (max_{i=l}^{r-1}{d_i}) 都很好处理,啥都能维护的亚子。

    不好处理就枚举呗。

    枚举以 (d_i) 为最大值的区间 ([lp_i,rp_i]) ,这个可以单调栈 (O(n)) 搞。

    由于要保证 (iin [l,r]) ,那么(l) 一定在 ([lp_i,i]) 内,(r)([i,rp_i]) 内。然后直接用一个可以处理静态询问区间最大值的数据结构维护一下 (a*i-sc_i) 即可,注意下标!

    还有一种情况不需要减 (d_i) ,就是 (l=r) 的时候,枚举特判一下即可

    #define int long long
    inline int rd() {
        int a=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))a=a*10+(ch^48),ch=getchar();
        return a*f;
    }
    #define N 300009
    int n,a,ans;
    int c[N],sc[N],d[N];
    int lg[N],pw2[25];
    int st[N],top,lp[N],rp[N];
    struct ST_Table {
        int st[20][N];
        void init() {
            for(int i=1;i<=19;++i)
                for(int j=1;j+pw2[i]-1<=n;++j)
                    st[i][j]=max(st[i-1][j],st[i-1][j+pw2[i-1]]);
        }
        int ask(int l,int r) {
    		if(l>r)return 0;
            int x=lg[r-l+1];
            return max(st[x][l],st[x][r-pw2[x]+1]);
        }
    }s[2];
    void st_init() {
        lg[0]=-1,pw2[0]=1;
        for(int i=1;i<N;++i)lg[i]=lg[i>>1]+1;
        for(int i=1;i<=20;++i)pw2[i]=pw2[i-1]<<1;
    }
    signed main() {
        n=rd(),a=rd();
        st_init();
        for(int i=1;i<=n;++i)d[i]=rd(),sc[i]=sc[i-1]+(c[i]=rd());
        for(int i=1;i<n;++i)d[i]=(d[i+1]-d[i])*(d[i+1]-d[i]);
        for(int i=1;i<n;++i) {
            while(top&&d[st[top]]<d[i])rp[st[top--]]=i-1;
            lp[i]=st[top]+1,st[++top]=i;
        }
        while(top)rp[st[top--]]=n-1;
        for(int i=1;i<=n;++i)
            s[0].st[0][i]=sc[i-1]-a*(i-1),
            s[1].st[0][i]=a*(i+1)-sc[i+1];
        s[0].init(),s[1].init();
        for(int i=1;i<=n;++i)ans=max(ans,a-c[i]);
        for(int i=1;i<n;++i)
            ans=max(ans,s[0].ask(lp[i],i)+s[1].ask(i,rp[i])-d[i]);
        printf("%lld
    ",ans);
        return 0;
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    “老人之心”
    封装,策略模式,Asp换脸
    简单随机
    “辜新星”
    储存出题改进
    git
    读“徐宥”
    太白非技术类随笔(猛击这里!!!)
    python_模块
    python_day7学习笔记
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13610567.html
Copyright © 2011-2022 走看看