HDU 6438 Buy and Resell (CCPC网络赛) 堆 贪心
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
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.
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.
Sample Input
Sample Output
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
1、首先是第一個入隊,第二個入隊時開始判斷,第二個是2,堆頂1,可以構成交易,進行交易,把1彈出隊。買的要彈出隊列,但賣的不用,因為賣的地方可以再買,而買的地方不會再賣,因為如果後面要發生反悔,中間著永遠是賣的地方(看下面的2、就明白了),2只需要打上一個賣出標誌、交易次數+1,然後進隊。
2、10入隊,可以和堆頂的2構成買賣,但2有賣出標誌,這個時候,從1買入從2賣出,再從2買入從10賣出,相當於從1買入從10買出,2成了中間量。為了減少次數,我們直接讓1和10構成交易,2的賣出標誌去掉(不需要出隊)、交易次數不變,還是1次。
3、9入隊,可以和堆頂的2構成交易,2沒有賣出標誌了,就是一個普通買入地,把2彈出隊列。交易次數+1
這樣這組數據就跑完了。發生兩次交易,交易金額是-1-2+10+9=16,發生的交易次數是2,時間是兩倍:4
這裡用了優先隊列來維護一個最小堆
下面是AC代碼
#include<bits/stdc++.h> #define N 100009 using namespace std; typedef long long ll; struct node { int x,v; //x是坐標,v是這個城市的價格 bool sell; friend bool operator <(node a,node b) { if(a.v==b.v) return !a.sell; //同價格中:曾經在那個城市買過的優先 return a.v > b.v; //優先隊列中價格小的優先 } }; int main() { int T; scanf("%d",&T); while(T--) { priority_queue<node> q; int n; scanf("%d",&n); int a; scanf("%d",&a); //第一個入隊 node temp; temp.x=1; temp.v=a; temp.sell=false; q.push(temp); ll ans=0,time=0; for(int i=2;i<=n;i++) { int a; scanf("%d",&a); temp.sell=false; if(a>q.top().v) //如果在這之前有價格比它低,則賣出 { node top=q.top(); q.pop(); ans+=a-top.v; if(top.sell) //如果曾經在那個城市賣出過,又再那個城市買入 { top.sell=false; //那就相當于沒有交易過,兩次交易合為一次,故次數不加 q.push(top); } else time++; //反之次數增加 temp.sell=true; } temp.x=i; //當前城市入隊 temp.v=a; q.push(temp); } printf("%lld %lld\n",ans,time*2); //一次交易涉及兩個城市,時間是交易次數的兩倍 } }