HDU - 6438 Buy and Resell(思维+ 贪心)

题目链接

题意

t组输入,每组n个城市,给出每个城市的货物的价格,在每个城市可以进行三个操作:购买货物,卖出货物,不做操作,问从城市1到城市n(不能返回)最多能获得多少利润,且操作数最少(买和卖分别算一次操作)。

思路

首先,对于 1 2 10,我们可以这样考虑:在1号城市买入,在2号城市卖出,利润为2-1 = 1,但是我们发现3号城市利润更高,所以在2号城市的时候我们假装买入一份价格为2的货物,然后在3号卖出,重述一次整个过程:城市1买入(-1),城市2卖出(-1+2),城市二买入(-1+2-2),城市三卖出(-1+2-2+10 = 9),其实就相当于在1号买入,3号卖出,2号城市当作跳板,同样,操作数就算2次,那么我们可以把货物分成两类——直接购买的货物,当作跳板虚假买入的货物,那么直接购买的货物卖出后操作数就是2,跳板货物对操作数没有影响,所以操作数为0。如此,我们可以想到用一个优先队列维护一个结构体,结构体里存货物价格和类型(对操作数的影响,0或2),按照先价格从小到大,再类型从小到大的顺序出队。遍历一次所有城市,如果当前城市的价格大于队内最小的价值,说明卖出有利润,卖出并pop掉,再压入当前城市价格的两种类型的货物(具体看代码),最后输出即为答案。

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
using namespace std;
const int maxn = 1e5 + 10;
const double PI = acos(-1.0);

struct node {
    int val, type;
    bool operator<(const node b) const {//重载符号,达到先按照价格后按照类型从小到大排列
        if (val != b.val) return val > b.val;
        return type > b.type;
    }
};

priority_queue<node> q;
int main(int argc, char const *argv[]) {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        while (!q.empty()) q.pop();
        int n;
        cin >> n;
        LL ans = 0, cnt = 0;
        while (n--) {
            int x;
            cin >> x;
            node p;
            p.val = x;
            p.type = 2;
            if (!q.empty() && q.top().val < x) {//如果队内最小价格小于当前城市的价格,说明有利可图,卖出
                ans += x - q.top().val;
                cnt += q.top().type;
                q.pop();
                q.push(p);//压入两种类型的货物
                p.type = 0;//当前货物可能是当作跳板卖出的,所以也要压入跳板
                q.push(p);
            } else
                q.push(p);//当前城市不卖出货物,只有可能买入,故压入类型为操作数为2的货物
        }
        cout << ans << ' ' << cnt << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值