• 【贪心】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);
    }
  • 相关阅读:
    field_automation源码分析
    uvm设计分析——field automation
    uvm设计分析——tlm
    gedit emacs
    C语言---数据结构(内建,数组,自定义)
    C语言---选择结构和循环结构
    C语言---变量与函数
    C语言---指针
    C语言--函数
    009-多线程-锁-JUC锁-Semaphore 信号量【控制一定数量的许可(permit)的方式,来达到限制通用资源访问的目的】
  • 原文地址:https://www.cnblogs.com/kkkek/p/11865180.html
Copyright © 2020-2023  润新知