Buy and Resell HDU - 6438 (贪心+优先队列维护)

Buy and Resell

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1713    Accepted Submission(s): 600


 

Problem Description

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

 

 

Source

2018中国大学生程序设计竞赛 - 网络选拔赛

大致题意:

有若干个城市,都销售和购买某种商品,问一商人在从头到尾走过这些城市时,如何通过最少的购买次数,获得最大的价值

思路:

每读入一个新的城市的价格,假如在优先队列中没有比他小的元素则将之加入队列,并将他的状态标记为1,如果有比他小的元素,则将那个元素删除,并向队列中加入两个城市的价值,并将两个的状态一个标记为1,一个标记为0,如果被删除元素的状态为0则买卖次数不变换,如果为1则买卖次数加2。

原理说明:

4

1 2 3 4

为例。

首先我们读入一个1,此时队列为空,所以将1的状态标记为1再加入。

此时队列中的元素为 (1,1)

再读入一个2,此时队顶元素为(1,1),所以将2的状态标记为0,1加入其中,并将(1,1)弹出,买卖次数加2

此时队列中的元素为 (2,1),(2,0)

再读入一个3,此时队顶元素为(2,0),所以将3的状态标记为0,1加入其中,并将(2,0)弹出,买卖次数不变化

此时队列中的元素为(2,1),(3,1),(3,0)

再读入一个4,此时队顶元素为(2,1),所以将4的状态标记为0,1加入其中,并将(2,1)弹出,买卖次数加2

此时队列中的元素为(3,1),(3,0),(4,1),(4,0)

让我们来分析其中的每一步到底都意味着什么。

首先我们把(1,1)弹出时,意味着我们选择了把1卖成2,但是这种选择不一定是最优的卖法,所以我们留下一定的返回余地,也就是(2,0)但是考虑到如果,2成功反悔的话,2就变成了没有买的情况了,我们又可以买2了,如在下面中,当3出现后,1不再选择直接卖给2而是直接卖给三,但是其中买卖所需的次数已经在卖给2的时候计算过了,所以不再重复计算。而在四出现后,2又一次变成了最好的选项,而且由于2曾经被反悔,所以现在的2是一个全新的未被操作过的2,所以操作这个2的时候买卖的次数需要加2。而加入2未反悔的话,(2,0)的状态总是会在(2,1)的状态之前所以总是会先进行反悔操作,才会对之真正进行匹配。

AC代码:

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
typedef pair<long long,bool> plb;
typedef long long LL;
priority_queue<plb,vector<plb>,greater<plb> > q;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		while(!q.empty()) q.pop();
		int n;
		scanf("%d",&n);
		LL num=0,ans=0;
		for(int i=0;i<n;i++)
		{
			LL val;
			scanf("%d",&val);
			if(!q.empty()&&q.top().first<val)
			{
				num++;
				plb x=q.top();q.pop();
				if(x.second==0) num--;
				else num++;
				ans+=val-x.first;//配对成功再加上值
				q.push(plb(val,1));//假如被反悔了,这个元素就没有真正被卖所以就会来到队顶等着被重新卖出
				q.push(plb(val,0));//这个可以进行反悔的,可以观察到如果是卖这一项的话并不需要次数
			}else q.push(plb(val,1));//如果无法获得利益就先储存
		}
		cout<<ans<<' '<<num<<endl;
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值