1. 程式人生 > >HDU 6438 Buy and Resell(貪心+優先佇列+set)

HDU 6438 Buy and Resell(貪心+優先佇列+set)

Description

nn個城市,第ii個城市商品價格為aia_i,從11城市出發依次經過這nn個城市到達nn城市,在每個城市可以把手頭商品出售也可以至多買一個商品,問最大收益以及在最大收益下的最少交易次數

Input

第一行一整數TT表示用例組數,每組用例首先輸入一整數nn表示城市數量,之後輸出nn個整數aia_i表示每個城市商品單價

(1T250,1n105,n5105)(1\le T\le 250,1\le n\le 10^5,\sum n\le 5\cdot 10^5)

Output

輸出最大收益以及在最大收益下的最少交易次數

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

Solution

貪心,用優先佇列維護當前位置之前所有的商品價格,每次選取價格最低的買入,如果該價格的商品之前是賣出的狀態,那麼就合併這四次交易變成兩次交易,需要用一個mulsetmulset維護賣出狀態的商品,時間複雜度O(nlogn)O(nlogn)

Code

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
#define maxn 100005
int T,n,a[maxn];
priority_queue<int,vector<int>,greater<int> >que;
multiset<int>s;
multiset<int>::iterator it;
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		s.clear();
		while(!que.empty())que.pop();
		ll ans=0;
		int num=0;
		for(int i=1;i<=n;i++)
		{
			if(!que.empty()&&que.top()<a[i])
			{
				int x=que.top();
				que.pop();
				it=s.find(x);
				if(it==s.end())num+=2;
				else que.push(x),s.erase(it);
				ans+=a[i]-x;
				s.insert(a[i]);
			}
			que.push(a[i]);
		}
		printf("%lld %d\n",ans,num);
	}
	return 0;
}