• gym102201E_Eat Economically


    题意

    (2n)个物品,分别有(a,b)属性,对于(i=1...n),选择(i)(a)属性和(i)(b)属性,且每个物品只能作为一种属性的贡献,求最小的值。

    分析

    • 看了题解补了两天... 应该叫做可反悔的贪心,或者其实就是网络流?不过因为是特殊的图,所以可以用优先队列来优化。
    • 维护四个优先队列,分别是未使用的(a)属性,未使用的(b)属性,已使用的(a)属性转化为(b)属性的花费,已使用的(b)属性转化为(a)属性的花费。
    • 对一般情况,每次取出最小(a)属性,取出最小(b)属性转化为(a)属性的花费,以及最小的(b)属性,判断哪种策略更优,对(b)属性同理。
    • 很多细节需要注意
      • 相同属性值,选择后反悔成另一种属性的花费更小的优先(无需绝对值)。比如(3,2)比(3,4)优先。
      • 两种策略的花费相同时,选择直接取出的策略,因为另一种策略需要从另一种最小堆中取出一个元素,使得堆顶元素变大。
      • 在前两个最小堆中取元素时需要判断取出元素是否已访问过。
      • 进行反悔的元素需要将花费取反然后放到另一个反悔队列里面去。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5e5+50;
    struct node{
        int id;
        ll val,sec;
        bool operator <(const node& rhs)const{
            if(val!=rhs.val){
                return val>rhs.val;
            }else{
                return sec-val>rhs.sec-rhs.val;
            }
        }
    };
    priority_queue<node> lc,dn,ltd,dtl;
    int n,vis[N];
    ll l[N],d[N];
    int main(){
    //    freopen("in.txt","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++){
            scanf("%lld%lld",&l[i],&d[i]);
            lc.push(node{i,l[i],d[i]});
            dn.push(node{i,d[i],l[i]});
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            while(!lc.empty() && vis[lc.top().id]){
                lc.pop();
            }
            if(lc.empty()){
                auto t=dtl.top();
                dtl.pop();
                ans+=t.val;
                auto g=dn.top();
                dn.pop();
                ans+=g.val;
                ltd.push(node{t.id,d[t.id]-l[t.id]});
                dtl.push(node{g.id,l[g.id]-d[g.id],0});
            }else{
                auto a=lc.top();
                while(vis[a.id]){
                    lc.pop();
                    a=lc.top();
                }
                while(!dn.empty() && vis[dn.top().id]){
                    dn.pop();
                }
                if(dtl.empty() || dn.empty()){
                    ans+=a.val;
                    lc.pop();
                    vis[a.id]=1;
                    ltd.push(node{a.id,d[a.id]-l[a.id],0});
                }else{
                    auto b=dtl.top();
                    auto c=dn.top();
                    if(a.val<=b.val+c.val){
                        ans+=a.val;
                        lc.pop();
                        vis[a.id]=1;
                        ltd.push(node{a.id,d[a.id]-l[a.id],0});
                    }else{
                        ans+=b.val+c.val;
                        dtl.pop();
                        dn.pop();
                        vis[c.id]=1;
                        ltd.push(node{b.id,d[b.id]-l[b.id],0});
                        dtl.push(node{c.id,l[c.id]-d[c.id],0});
                    }
                }
            }
            while(!dn.empty() && vis[dn.top().id]){
                dn.pop();
            }
            if(dn.empty()){
                auto t=ltd.top();
                ltd.pop();
                ans+=t.val;
                auto g=lc.top();
                lc.pop();
                ans+=g.val;
                dtl.push(node{t.id,l[t.id]-d[t.id],0});
                ltd.push(node{g.id,d[g.id]-l[g.id],0});
            }else{
                auto a=dn.top();
                while(vis[a.id]){
                    dn.pop();
                    a=dn.top();
                }
                while(!lc.empty() && vis[lc.top().id]){
                    lc.pop();
                }
                if(ltd.empty() || lc.empty()){
                    ans+=a.val;
                    dn.pop();
                    vis[a.id]=1;
                    dtl.push(node{a.id,l[a.id]-d[a.id],0});
                }else{
                    auto b=ltd.top();
                    auto c=lc.top();
                    if(a.val<=b.val+c.val){
                        ans+=a.val;
                        dn.pop();
                        vis[a.id]=1;
                        dtl.push(node{a.id,l[a.id]-d[a.id],0});
                    }else{
                        ans+=b.val+c.val;
                        ltd.pop();
                        lc.pop();
                        vis[c.id]=1;
                        dtl.push(node{b.id,l[b.id]-d[b.id],0});
                        ltd.push(node{c.id,d[c.id]-l[c.id],0});
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Codechef MSTONES Milestones
    Gym101620C Cumulative Code
    bootstrap组件-导出数据
    安装pip工具
    权限管理系统---django版本
    tornado 路由、模板语言、session
    django 连接mysql
    django 表结构
    ajax和原生ajax、文件的上传
    django的cookie和session
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11609462.html
Copyright © 2020-2023  润新知