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

Buy and Resell         HDU - 6438

https://cn.vjudge.net/problem/HDU-6438
The Power Cube is used as a stash of Exotic Power. There are n cities numbered 1,2,…,n where allowed to trade it. The trading price of the Power Cube in the i-th city is ai dollars per cube. Noswal is a foxy businessman and wants to quietly make a fortune by buying and reselling Power Cubes. To avoid being discovered by the police, Noswal will go to the i-th city and choose exactly one of the following three options on the i-th day:

  1. spend ai dollars to buy a Power Cube
  2. resell a Power Cube and get ai dollars if he has at least one Power Cube
  3. do nothing

Obviously, Noswal can own more than one Power Cubes at the same time. After going to the n cities, he will go back home and stay away from the cops. He wants to know the maximum profit he can earn. In the meanwhile, to lower the risks, he wants to minimize the times of trading (include buy and sell) to get the maximum profit. Noswal is a foxy and successful businessman so you can assume that he has infinity money at the beginning.
Input
There are multiple test cases. The first line of input contains a positive integer T (T≤250), indicating the number of test cases. For each test case:
The first line has an integer n. (1≤n≤105)
The second line has n integers a1,a2,…,an where ai means the trading price (buy or sell) of the Power Cube in the i-th city. (1≤ai≤109)
It is guaranteed that the sum of all n is no more than 5×105.
Output
For each case, print one line with two integers —— the maximum profit and the minimum times of trading to get the maximum profit.
Sample Input
3
4
1 2 10 9
5
9 5 9 10 5
2
2 1
Sample Output
16 4
5 2
0 0

Hint
In the first case, he will buy in 1, 2 and resell in 3, 4.

profit = - 1 - 2 + 10 + 9 = 16
In the second case, he will buy in 2 and resell in 4.

profit = - 5 + 10 = 5
In the third case, he will do nothing and earn nothing.

profit = 0

题目大意:

有T组样例,每组n个价格,从第一个价格到最后一个价格,每到一个价格你有三种方法,以当前价格卖出,以当前价格买进,不买不卖,开始你有无限的钱
问走到最后你最多能赚多少钱,你能预先知道每个价格

思路:

贪心+优先队列
策略
每次从手上的和卖出的选最小的卖出(现在的必须比最小的大)
若现在的比最小的都小,那就买进现在的

代码:
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#define ll long long
using namespace std;
int n,m;
ll ans,tmp,x,num;
priority_queue< ll,vector<ll>,greater<ll> >q,p;//q表示手上的,p表示已经卖出去的
int main() {
	int T;
	scanf("%d", &T);
	while(T--){
		scanf("%d", &n);
		ans=num=0;
		while(!p.empty()) p.pop();//清空队列
		while(!q.empty()) q.pop();
		for(int i=0;i<n;i++){
			scanf("%lld", &x);
			if(!p.empty()){//从已经卖出去的价格和手中买了的价格中挑一个最小的以当前价格卖出去
				tmp=p.top();
				if(tmp<x&&!q.empty()&&q.top()<tmp){//手上的价格最小,卖掉手上的
					num++;
					ans+=x;
					q.pop();
					p.push(x);
				}else if(tmp<x){//卖出去的比现在的小,回收卖掉的,在以现在的价格卖出去
					p.pop();
					q.push(tmp);
					ans-=2*tmp;
					ans+=x;
					p.push(x);
				} else if(!q.empty()&&q.top()<x){//卖出去的比现在的大,手上的小于现在的,直接卖掉手上的
					num++;
					p.push(x);
					ans+=x;
					q.pop();
				}else{//现在的最小,买进现在的
					ans-=x;
					q.push(x);
				}
			}
			else if(!q.empty()&&q.top()<x){//没有卖出去的,现在的比手上的大,卖掉手上的
				num++;
				p.push(x);
				ans+=x;
				q.pop();
			}else{//现在的比手上的小,买进现在的
				ans-=x;
				q.push(x);
			}
		}
		while(!q.empty()){//手上还有剩余的,全部卖出
			ans+=q.top();
			q.pop();
		}
		printf("%lld %lld\n", ans, num*2);
	}
	return 0;
}

参考:
HDU 6438 Buy and Resell(贪心)
https://blog.csdn.net/LSD20164388/article/details/82055089

猜你喜欢

转载自blog.csdn.net/weixin_44410512/article/details/86701769
今日推荐