HDU 6438 Buy and Resell(贪心)

Buy and Resell

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


 

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

题意:T组样例,每组n个价格。依次从第一个物品买到最后一个物品,你每走到一个价格,可以以当前价格买进一个物品,或者将你手中的一个物品以当前价格卖出,或者不买也不卖。问你最后获利多少(最后手里不能有物品),和买卖次数是多少。

思路:首先今天压线出线了。。。值得庆祝,但是也是对我们一个警告。。。买卖次数是相等的,只统计一个最后乘二即可。这类题出了不少了。。。考虑贪心。考虑每个价格的买卖情况。维护两个优先队列(小的在队头)。分别表示买进来的物品价格(q)和卖出去的物品价格(p)。对于当前价格,如果手中已经买了的物品的最小值(q.top())<卖出去的物品的最小值(p.top())<当前价格x,那么我们就把当前手中最便宜的那个物品卖掉,否则如果已经卖出去的物品的最小值<当前价格x,我们就再把它买回来,以x价格再卖出去(赚差价),否则如果当前手里的物品最小值<当前价格x,就卖出去,否则就先按价格x买了(因为以后可能以高价卖出)。

然后如果还没有卖出去的就只进行后两步比较操作即可。

然后最后手里如果还有没卖出去的,我们就相当去没买(再按原价卖出)。

如果还有不懂的,欢迎评论。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
ll ans,tmp,x,num;
priority_queue<ll,vector<ll>,greater<ll> >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;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/82055089