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

版权声明:欢迎转载,请注明此博客地址。 https://blog.csdn.net/Ever_glow/article/details/82054350

Buy and Resell

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

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个商店,每个商店的商品的买入或卖出的价格固定,问最大能得到的利润是多少,保证最大利润的同时需要保证交换次数最小,输出利益和次数。

拿示例来看,1 2 10 9,买1卖10,买2卖9,想办法维护一个序列,求出最大点前的最小值,然后最大值依次递减,最小值依次递增。易得买1卖2后,买2卖10的和正好是买1卖10的结果,也就是答案具有传递性,而且卖出最大值的时候一定是存在交换的,这样方便记录交换次数。首先维护一个递增的序列,当前点大于队首元素的时候,证明此时的物品是可以交换的,加入结果,并且将此点设为被使用,放入序列中。若是此元素再次出现在队首,证明出现1 2 10的情况,然后去除此点的一个分身,也就是被标记过的元素。这里标记元素后方便最后统计交换次数,所以每个点没分为两个,交换的话放入一个标记点,记为交换,放入一个未标记点,作为下次继续可交换的值。最后输出结果,统计交换次数。

语言难以表达清楚,具体可看代码,模拟此过程。
代码实现:

 

/*
Look at the star
Look at the shine for U
*/
#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define sl(x) scanf("%lld",&x)
using namespace std;
const int N = 1e6+5;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
struct node{
    ll num,index;
    node(ll a,ll b)
    {
        num = a;
        index = b;
    }
    friend bool operator < (node a,node b)
    {
           if(a.num == b.num) return a.index < b.index;
           return a.num > b.num;
    }
};
priority_queue <node> q;
int main()
{
    ll t,p,i,j,k,n,x;
    sl(t);
    while(t--)
    {
        sl(n);
        ll ans = 0,count = 0;
        for(i = 0;i < n;i++)
        {
            sl(x);
            q.push(node(x,0));
            node temp = q.top();
            if(x > temp.num)
            {
                ans += x-temp.num;
                q.pop();
                q.push(node(x,1));
            }
        }
        while(!q.empty())
        {
            if(q.top().index) count++;
            q.pop();
        }
        printf("%lld %lld\n",ans,count*2);
    }
}

猜你喜欢

转载自blog.csdn.net/Ever_glow/article/details/82054350