杭电多校第十场 6698 Coins STL瞎搞..

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6698

题意:

你现在有n个箱子,每个箱子有左右两边,分别放着 L [ i ] , R [ i ] L[i],R[i] L[i],R[i]币值的硬币,对于每个箱子你只有三种拿硬币的状态,一个都不拿,只拿左边的,或者左边右边一起拿。你现在要一个个的拿硬币一直到全部拿完,问你每次拿完之后手上最高的价值是多少。

做法:

我们每次拿硬币更新答案的时候,对目标箱子的变化只有四种。如下图。
在这里插入图片描述在这里插入图片描述

所以我们只需要记录下面五个堆,每次都查看最大的类型进行转化即可。
在这里插入图片描述

代码

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
using namespace std;
typedef long long ll;
const int maxn=100005;
struct bigger{
    int add,id;
    bigger(int add,int id):add(add),id(id){}
    bool operator < (const bigger &a)const{
        return add<a.add;
    }
};
struct smaller{
    int sub,id;
    smaller(int sub,int id):sub(sub),id(id){}
    bool operator < (const smaller &a)const{
        return sub>a.sub;
    }
};
priority_queue<bigger> ze_to_one,ze_to_two,one_to_two;
priority_queue<smaller> one_to_ze,two_to_one;
int n,fi[maxn],se[maxn],ans,num[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        while(!ze_to_one.empty()) ze_to_one.pop();
        while(!ze_to_two.empty()) ze_to_two.pop();
        while(!one_to_two.empty()) one_to_two.pop();
        while(!one_to_ze.empty()) one_to_ze.pop();
        while(!two_to_one.empty()) two_to_one.pop();
        scanf("%d",&n);
        ans=0;
        rep(i,1,n){
            scanf("%d%d",&fi[i],&se[i]);
            ze_to_one.push(bigger(fi[i],i));
            ze_to_two.push(bigger(fi[i]+se[i],i));
            num[i]=0;
        }
        rep(i,1,2*n){
            int maxx=-1,ty=-1;
            while(!ze_to_one.empty()) {
                if(num[ze_to_one.top().id]!=0) {
                    ze_to_one.pop(); continue;
                }
                bigger tmp=ze_to_one.top();
                if(maxx<tmp.add){
                    maxx=tmp.add; ty=1; break;
                }
                break;
            }
            while(!one_to_two.empty()) {
                if(num[one_to_two.top().id]!=1) {
                    one_to_two.pop(); continue;
                }
                bigger tmp=one_to_two.top();
                if(maxx<tmp.add){
                    maxx=tmp.add; ty=2;
                }
                break;
            }
            while(!one_to_ze.empty()&&!ze_to_two.empty()){
                if(num[ze_to_two.top().id]!=0) {
                    ze_to_two.pop(); continue;
                }
                if(num[one_to_ze.top().id]!=1) {
                    one_to_ze.pop(); continue;
                }
                bigger tmp1=ze_to_two.top();
                smaller tmp2=one_to_ze.top();
                if(maxx<tmp1.add-tmp2.sub){
                    maxx=tmp1.add-tmp2.sub;
                    ty=3;
                }
                break;
            }
            while(!two_to_one.empty()&&!ze_to_two.empty()){
                if(num[two_to_one.top().id]!=2) {
                    two_to_one.pop(); continue;
                }
                if(num[ze_to_two.top().id]!=0) {
                    ze_to_two.pop(); continue;
                }
                bigger tmp1=ze_to_two.top();
                smaller tmp2=two_to_one.top();
                if(maxx<tmp1.add-tmp2.sub){
                    maxx=tmp1.add-tmp2.sub;
                    ty=4;
                }
                break;
            }
            if(ty==1){
                bigger tmp=ze_to_one.top(); ze_to_one.pop();
                ans+=tmp.add; num[tmp.id]=1;
                one_to_two.push(bigger(se[tmp.id],tmp.id));
                one_to_ze.push(smaller(fi[tmp.id],tmp.id));
            }
            if(ty==2){
                bigger tmp=one_to_two.top(); one_to_two.pop();
                ans+=tmp.add;  num[tmp.id]=2;
                two_to_one.push(smaller(se[tmp.id],tmp.id));
            }
            if(ty==3){
                bigger tmp1=ze_to_two.top(); ze_to_two.pop();
                smaller tmp2=one_to_ze.top(); one_to_ze.pop();
                int d1=tmp1.id,d2=tmp2.id;
                ans+=maxx; num[d1]=2; num[d2]=0;
                two_to_one.push(smaller(se[d1],d1));
                ze_to_one.push(bigger(fi[d2],d2));
                ze_to_two.push(bigger(fi[d2]+se[d2],d2));

            }
            if(ty==4){
                bigger tmp1=ze_to_two.top(); ze_to_two.pop();
                smaller tmp2=two_to_one.top(); two_to_one.pop();
                int d1=tmp1.id,d2=tmp2.id;
                ans+=maxx; num[d1]=2,num[d2]=1;
                one_to_two.push(bigger(se[d2],d2));
                one_to_ze.push(smaller(fi[d2],d2));
                two_to_one.push(smaller(se[d1],d1));
            }
            printf("%d%c",ans,i==2*n?'\n':' ');
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值