• 题解-CF436E Cardboard Box


    题面

    CF436E Cardboard Box

    (n) 个关卡,对每个关卡可以花 (a_i) 时间得到 (1) 颗星,或花 (b_i) 时间得到 (2) 颗星,或不玩。问获得 (m) 颗星最少需要多少时间。

    数据范围:(1le nle 3cdot 10^5)(1le mle 2n)(a_i<b_i)


    题解

    蒟蒻做这题时已经知道是反悔贪心了,但是做了 (4) 个小时做不出来。于是去看题解,感觉这个 (5) 堆做法太非人类了,于是去看 CF 题解和代码后总结出了蒟蒻的不用反悔贪心的做法和题解。

    如果不反悔贪心,那么每一步必须保证没有后效性地最优。

    很明显如果只有 (a_i),排序可以满足这个条件。

    这题最朴素的错误做法是用一个小顶堆,刚开始把所有 (a_i) 丢进去,然后 (m) 次每次取堆顶,如果选了 (a_i)(b_i-a_i) 也丢进去。

    如果 (a_i) 都很大,(b_i-a_i) 都很小这样显然是亏的。

    假如某个 (i) 打出 (2) 星是当前最优,如果 (a_i) 已经取了按照上面的办法肯定没有问题;但是如果 (a_i) 都没取,(a_i) 不一定是单个中的最优。

    所以这篇题解最重要的骚操作就来了:选之前权衡,选两个的最优还是一个的最优:哪个更优?

    可以用一个 vis 数组记录打了那些关卡,每次把打了的从堆中扔掉,这样就可以假定堆中的都是没有打过的了。


    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    #define x first
    #define y second
    #define bg begin()
    #define ed end()
    #define pb push_back
    #define mp make_pair
    #define sz(a) int((a).size())
    #define R(i,n) for(int i(0);i<(n);++i)
    #define L(i,n) for(int i((n)-1);~i;--i)
    const int iinf=0x3f3f3f3f;
    const ll linf=0x3f3f3f3f3f3f3f3f;
    
    //Data
    const int N=3e5,sN=N<<1;
    int n,m,star[N];
    ll a[sN],ns; bool vis[sN];
    priority_queue<pair<ll,int>> o,t;
    void ref(priority_queue<pair<ll,int>> &q){
        while(sz(q)&&vis[q.top().y]) q.pop();
    }
    
    //Main
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0),cout.tie(0);
        cin>>n>>m;
        R(i,n) cin>>a[i]>>a[i+n],a[i+n]-=a[i],
            o.push(mp(-a[i],i)),t.push(mp(-a[i]-a[i+n],i));
        while(m--){
            ref(o),ref(t);
            int i=o.top().y; o.pop(),ref(o);
            if(m&&sz(t)&&a[i]-o.top().x>=-t.top().x)
                o.push(mp(-a[i],i)),i=t.top().y,t.pop();
            i<n&&(o.push(mp(-a[i+n],i+n)),true);
            ns+=a[i],star[i%n]++,vis[i]=true;
        }
        cout<<ns<<'
    ';
        R(i,n) cout<<star[i],i==n-1&&(cout<<'
    ');
        return 0;
    }
    
    /*
    
    可以考虑不反悔:权衡一个两个哪个优!
    
    */
    

    祝大家学习愉快!

  • 相关阅读:
    点 多边形内外判断
    Winform获取js变量值
    软件和系统之间的微妙
    c# 读写json文件
    不规则图形重心
    c# winform 打开html界面(含引用外部文件js)
    c# GDI 画圆,可以调整大小等功能
    mysql 查找乱码数据
    类实例的拷贝
    Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等
  • 原文地址:https://www.cnblogs.com/George1123/p/13970224.html
Copyright © 2020-2023  润新知