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
大致题意:
有若干个城市,都销售和购买某种商品,问一商人在从头到尾走过这些城市时,如何通过最少的购买次数,获得最大的价值
思路:
每读入一个新的城市的价格,假如在优先队列中没有比他小的元素则将之加入队列,并将他的状态标记为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;
}
}