Buy and Resell
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 742 Accepted Submission(s): 194
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
Recommend
chendu | We have carefully selected several similar problems for you: 6447 6446 6445 6444 6443
题意:从左到右,对于每一个数,可以选择买或者卖自己有个一个数,求最大利润。
解题思路:优先队列,从左到右,对于每一个数,在他左边,找一个未匹配的最小的数,与他匹配,这样肯定是最大值。找最小的数用优先队列维护。
#include<iostream>
#include<queue>
#include<string.h>
#include<functional>
using namespace std;
typedef long long ll;
ll A[100005];
struct node
{
friend bool operator< (node n1, node n2)
{
if(n1.first==n2.first)
return n1.pi<n2.pi;//如果相等,那就找已经有匹配的,这样可以省次数。所以用-1初始化pi。
return n1.first > n2.first; //优先找小的
}
ll first; // 记录当前节点的值
ll second; //记录当前节点的下标
ll pi; //记录与当前节点匹配的那个节点
node(ll a,ll b,ll c=-1){
first=a;
second=b;
pi=c;
}
node(){
}
};
priority_queue<node> que;
int main(){
int T;
scanf("%d",&T);
for(int qqq=1;qqq<=T;qqq++){
int N;
scanf("%d",&N);
for(int i=0;i<N;i++)
scanf("%I64d",&A[i]);
while(!que.empty())
que.pop();
ll ans=0;
int ti=0;
for(int i=0;i<N;i++){
if(que.empty()){
que.push(node(A[i],i)); //第一个节点
continue;
}
node tp=que.top();
//如果大于,那就匹配
if(A[i]>tp.first){
ans+=A[i]-tp.first;//匹配
que.pop();
ti++;
int pi=tp.pi;
//如果当前匹配的那个点,已经被匹配了
if(pi!=-1){
ans-=tp.first-A[pi];//把那个匹配拆掉
ans-=A[i]-tp.first;//把刚刚加的,减回去
ans+=A[i]-A[pi];//再匹配
ti--;
tp.pi=-1;
que.push(tp);//被拆掉了,所以重新入队
que.push(node(A[i],i,pi));//当前节点也要入队
}
else
que.push(node(A[i],i,tp.second));//当前节点也要入队
}
else{
que.push(node(A[i],i));//当前节点也要入队
}
}
cout<<ans<<" "<<ti*2<<endl;
}
return 0;
}