zoukankan      html  css  js  c++  java
  • 【贪心】LuoguP5653 基础最优化练习题 (我想不到的贪心

    P5653

    题目大意:

    一个x初值为0,每次可以给x加上值y,y∈[-k,k],同时必须保证第i次操作后 xi≤ai。需要进行n次操作。

    有一个长度为n的序列 w,wi∈[-106,106]。

    设第i次操作后x的值为bi,要求最大化Σni=1biwi。输出最大值。

    数据范围:n106, 106wi106, 0ai108, 1k100。

    做法:

    y,w,a,b 所表示的 如题意。

    Σni=1biwi = Σni=1biΣij=1yi = Σni=1yiΣnj=ibj

    因为b是定值 所以 设cinj=ibj,即c是b的后缀和。

    所以有:Σni=1biwi = Σni=1yici

    设diij=1bj,即 d是y的前缀和。 

    则 限制 是

      对于所有di≤ai,对于所有y∈[-k,k]。 

    讲题人的题解是这么说的:

      此时我们可以考虑根据c 贪心。
      我们按照c 从大到小贪心,在能取的情况下尽量多取。
      这样子贪心的正确性可以通过网络流建模来证明。由于建模部分较 为复杂这里不再展开。

    所以,问题转化为,对于后缀和c,以c最大为最优,使c在不超“限制”的情况下取得对应y最大。

    对我来说,这个贪心很难想。

    知道这样子最优,做法也很难想。

    结果删删改改 ,没有多少代码。只是  想无 (:3_ヽ)_

    #include<bits/stdc++.h>
    #define debug printf("!");
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=1e6+50;
    
    struct P{
        ll w,lim;
        bool operator <(const P&p)const{return w>p.w;}
    }poi;
    ll a[maxn],b[maxn];
    priority_queue<P>que;
    
    /*
     从1到n 使得当前值取当前最优, 超过限制的值, 去找前i个值里小于 最优性低于当前值的最不优的可修改的值 减
     无法修改的值就 吐出来
     无法修改的值也 不要放进去
    
     这样子 才能使 最大的尽可能最优
     然后 这道题的贪心做法 要的就是使最大的值最优
    
     */
    
    int main()
    {
        int n;
        ll k,ans=0,sum=0,t,d,tt;
        scanf("%d%lld",&n,&k);
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)scanf("%lld",&b[i]);
        for(int i=n-1;i>=1;i--)b[i]+=b[i+1];
        for(int i=1;i<=n;i++)
        {
            if(b[i]<=0)
            {
                ans-=b[i]*k;
                sum-=k;
                t=sum-a[i];
                if(t<=0)continue;
                d=0;//累积可以抵消的限制
                while((!que.empty())&&d<t)
                {
                    poi=que.top();que.pop();
                    tt=min(t-d,poi.lim);
                    d+=tt;
                    poi.lim-=tt;
                    ans-=poi.w*tt;
                    sum-=tt;
                    if(poi.lim)
                    {
                        que.push(poi);break;
                    }
                }
                continue;
            }
            if(que.empty())
            {
                t=min(a[i]-sum,k);
                ans+=b[i]*t;
                sum+=t;
                que.push(P{b[i],t+k});
                continue;
            }
            ans+=b[i]*k;
            sum+=k;
            que.push(P{b[i],k+k});
            t=sum-a[i];//被限制
            if(t<=0)continue;
            d=0;//累积可以抵消的限制
            while((!que.empty())&&d<t)
            {
                poi=que.top();que.pop();
                tt=min(t-d,poi.lim);
                d+=tt;
                poi.lim-=tt;
                ans-=poi.w*tt;
                sum-=tt;
                if(poi.lim)
                {
                    que.push(poi);break;
                }
            }
        }
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    浏览器的渲染过程、渲染原理
    echarts简单用法快速上手
    gulp自动化构建工具使用
    vue路由高级语法糖
    git项目常用命令
    vue项目中快捷语法糖
    UpnP Hacking
    无线路由器认证会话劫持漏洞
    DNS缓存欺骗攻击
    识别无线设备
  • 原文地址:https://www.cnblogs.com/kkkek/p/11865180.html
Copyright © 2011-2022 走看看