CF865D Buy Low Sell High

題意翻譯

已知接下來N天的股票價格,天天你能夠買進一股股票,賣出一股股票,或者什麼也不作.N天以後你擁有的股票應爲0,固然,但願這N天內可以賺足夠多的錢.
輸入:
第一行一個整數天數N(2<=N<=300000).
第二行N個數字p1,p2...pN(1<=pi<=10^6),表示天天的價格.
輸出: N天結束後能得到的最大利潤.c++

題解

很是經典的貪心問題spa

 

用一個優先隊列小根堆。翻譯

假設每一個股票都買入。code

當前的股票價格>堆頂的時候,把這個股票加進去兩次。而後彈出堆頂。blog

不然加進去一次。隊列

把這個差價計入ans,ans+=price[i]-q.top()it

 

什麼意義呢?io

首先,咱們雖然假設都買入,可是並不必定都買。class

咱們只有在計算差價的時候,至關於纔會把某個價格買入,再以price[i]賣出。queue

而咱們把這個股票加進去兩次,

一次是正常的假設買入。爲了以後可能賺取差價。

另外一次是爲了反悔。

假設股票價格是:3 7 10

最優解是3買入,10賣出,賺7元

也就是說,我以3價格買入,但我會在7元的時候賣出。

可是7元賣可能不是最優秀的。

因此,咱們把7元再加進去,當輪到10元的時候,這個7元會再當作一個股票賣出ans+=10-7

發現,有意思的是,10-3=(10-7)+(7-3)

這就至關於3元買入,10元賣出。7元這天摸魚。

若是10後面假設還有一個20

即3,7,10,20

那麼,咱們10元以後,隊列裏有7,10,10

20元會7元買入,20元賣出。至關於7元這天買入了一股。

 

這樣下去,咱們總能把最少的價格買入,儘可能多的價格賣出。

若是不是最優秀的話,就不買不賣了。就是最後優先隊列裏剩下的一些。就是預約買入,可是實際沒有買入的部分。

 

#include<bits/stdc++.h>
using namespace std;
const int N=300000+10;
int n;
int p[N];
priority_queue<int,vector<int>,greater<int> >q;
long long ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i]);
        q.push(p[i]);
        if(!q.empty()&&q.top()<p[i]){
            ans+=p[i]-q.top();
            q.pop();
            q.push(p[i]);
        }
        
    }printf("%lld",ans);return 0;
}

總結:

反悔堆的比較厲害的應用了。

利用差價的關係,直接處理。

怎麼想到的?
首先要想到貪心,而後這個題確定要用一個反悔堆之類。

那麼,咱們假設先買入,仍是先都不買?

都不買太被動。

那就都買入,而後結算的時候,再真實買入。

可是對於不是最優的拋售天怎麼辦?

利用差價。便可。

相關文章
相關標籤/搜索