Buy and Resell (优先队列+贪心)

博客围绕hdu 6438题展开,题目是在一条直线上有n个点,各点有价值,初始能量为0,从一端走到另一端,每个点可花费价值获能量、花能量得价值或不操作,求最大价值。解析说明了物品三种状态及优先队列处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题 : hdu 6438

题意 :

有一条直线上n个点的价值 ai a i , 你的初始能量值为0 , 你从一端走到令一端 , 每个点都可以花费其价值获得一能量 , 或是花费一能量得到其价值 , 也可以什么都不做
求可以获得的最大价值

解析 :

每种物品都有3种状态,买,放置,买后卖出

我们对于每件物品默认先买掉即获得价值 , 并往优先队列中塞两个负的价值

当当前物品(B)为最小价值时,会pop掉一个自己,所以留下一个自己,对答案贡献x-x,相当于放置

如果不是最小价值,会pop掉前面的最小的一个(A),在此时减掉前面的价值A,加上自己的价值B,相当于买入当前卖掉前面,此时队列留下两个

为什么留下两个 ? 因为如果此物品需要卖 , 那么这两个都要pop即x-2*x , 在加入的时候pop掉了A , 加上自己的B , 所以留下两个

#include<bits/stdc++.h>
using namespace std;
#define mk make_pair
#define pill pair<int,int>
#define LL long long

int read(){
    int ans=0;char l=' ',c=getchar();
    while(!isdigit(c))l=c,c=getchar();
    while(isdigit(c))ans=ans*10+c-'0',c=getchar();
    if(l=='-')ans=-ans;return ans;
}

int main(){
    int t=read();
    while(t--){
        LL ans=0,ct=0;
        int n=read();
        priority_queue<pill>q;//价值小的优先卖出
        while(n--){
            int item=read();
            q.push(mk(-item,1));//pop时代表:买入当前物品卖出x
            q.push(mk(-item,2));//pop时代表:卖出x,相当于反悔买入x
            pill p=q.top();q.pop();
            int f=p.first,s=p.second;
            ans+=(LL)item+f;//默认先买入x
            if(s==1)ct++;//对于实际交易,买入一次必对应一次卖出,所以输出时乘2
        }
        printf("%lld %lld\n",ans,ct<<1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值