2018中国大学生程序设计竞赛 - 网络选拔赛 (hdu6438 Buy and Resell)

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

题意:有n天,在一天之内可以买东西或卖东西,也可以什么都不做,手里可以有多样物品,问n天过后最大赚多少钱。

思路:用一个优先队列维护一个堆,当堆中最小元素小于本位置元素就可以进行交换ans+=(x-q.top);如果q.top这个元素曾经交换过那么本次交换也就不算次数,然后要将x放入堆两个,因为其中一个代表q.top的。比如  5  9  10,就是先放5,然后9赚4,当10进入,最小值9交换赚1,最终相当于买5卖10.

代码:

map<int,int>vis;//标记该值之前买过几次
int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--)
    {
        int n;
        scanf("%d",&n);
        priority_queue<int, vector<int>, greater<int> > q;
        while(!q.empty()) q.pop();
        ll ans=0,cnt=0;
        vis.clear();
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(q.empty()||q.top()>=x) q.push(x);
            else
            {
                cnt++;
                int t=q.top();
                ans+=(x-t);
                q.pop();
                if(vis[t])
                {
                    cnt--;
                    vis[t]--;
                }
                q.push(x);
                q.push(x);//主要这里
                vis[x]++;
            }
        }
        printf("%lld %lld\n",ans,cnt*2);
    }
}
 

猜你喜欢

转载自blog.csdn.net/snayf/article/details/82083523
今日推荐