HDU - 6438 Buy and Resell (优先队列)(2018中国大学生程序设计竞赛 - 网络选拔赛 1001)

版权声明:Why is everything so heavy? https://blog.csdn.net/lzc504603913/article/details/82056603

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

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

 

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;
}

猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/82056603
今日推荐