【隊內胡策】洛聖都

【2017.10.24T3】
洛聖都,一個龐大且陽光普照的繁華都市,充滿了自我救贖的大師
們,貪官污吏們和落魄的名人們, 一羣被羨慕着的西方世界的居民
卻也正處於掙扎着生存的時代,衰落的經濟和廉價的道義讓這裏混
亂不堪。
題目描述
當你剛剛踏入洛聖都,就看見拉瑪爾走了過來。
“哦,兄弟,見到你可真高興。”
“來吧這裏是洛聖都, 你有我罩着包你滿意。”
“我們最近發現了一樁好活兒”拉瑪爾無不得意的說, “我們完全掌握了一種
股票的行情, 每天只需要到買倒賣,其他的什麼也不做。要來試試嗎?這纔是
文明人的賺錢方式。 ”
你可以在接下來的 N 天內完全預測某種股票的價格,你可以利用這個知識獲
利,但每天只能處理一份股票。 也就是說,你每天要麼買一份, 要麼賣一份,
要麼什麼也不做。 最初你擁有 0 份股票,當你不擁有任何股票時,你不能出售
股票。
在 N 天結束的時候, 你需要使自己手中的股票爲 0, 但希望在 N 天的過程中賺
到儘量多的錢。
輸入格式
輸入文件 resell.in
第一行輸入一個 N 表示天數。
接下來的 N 行每行一個整數 Pi 表示第 i 天某種股票的價格。
輸出格式
輸出文件 resell.out
一個整數爲賺到的最大金額。
樣例輸入 1
9
10 5 4 7 9 12 6 2 10
樣例輸出 1
20樣例輸入 2
20
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4
樣例輸出 2
41
數據範圍及提示
數據保證結果小於 MAX_longlong
對於 30%的數據: 1<=n<=10
對於 100%的數據: 1<=n<=300000

CF上的原題。登不上去,在本地測了一下。

原題面:
E. Buy Low Sell High
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You can perfectly predict the price of a certain stock for the next N days. You would like to profit on this knowledge, but only want to transact one share of stock per day. That is, each day you will either buy one share, sell one share, or do nothing. Initially you own zero shares, and you cannot sell shares when you don’t own any. At the end of the N days you would like to again own zero shares, but want to have as much money as possible.
Input
Input begins with an integer N (2 ≤ N ≤ 3·105), the number of days.
Following this is a line with exactly N integers p1, p2, …, pN (1 ≤ pi ≤ 106). The price of one share of stock on the i-th day is given by pi.
Output
Print the maximum amount of money you can end up with at the end of N days.
Examples
input
9
10 5 4 7 9 12 6 2 10
output
20
input
20
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4
output
41
Note
In the first example, buy a share at 5, buy another at 4, sell one at 9 and another at 12. Then buy at 2 and sell at 10. The total profit is  - 5 - 4 + 9 + 12 - 2 + 10 = 20.
英文題解(思路來源)
OrzWWQ

題解

題目條件:
① : 可以在接下來的 N 天內完全預測某種股票的價格;
② :每天只能處理一份股票,要麼買一份, 要麼賣一份,要麼什麼
也不做;
③ :在 N 天結束的時候, 你需要使自己手中的股票爲 0;
④ :希望在 N 天的過程中賺到儘量多的錢。
貪心。
每天給出一個股票價格,可以選擇在這一天以這一價格買入或賣出。
對於第三個條件不需要考慮,只需根據後面的處理過程假設在這一天
買入或賣出, 並不需要“持有”任何股票。
顯然,爲了賺到更多的錢,需要在價格較低時買入,價格較高時賣出。
但是並不知道具體在哪一天是買入或賣出的最好時間。 於是維護一個小根堆。 由於賣出的只能是先前已經買入的,所以小根堆中記錄當天
之前的信息。之後每加入一天的價格,將當前價格與堆頂(最小元素)
比較:
now>top, 將 now-top 加入答案;
now<=top, 將 now 放入堆。
然而這樣的策略並不完美。
例如: 3, 4,7
按照以上思路, 遍歷到 4 時發現 4 比 3 大就直接把 4-3 加入了答案,
實際上存在更優解: 7-3=4
觀察發現 7-3=(4-3)+(7-4) 也就相當於沒有用到 4
也就是說,如果只考慮 a小於b小於c 這樣的子序列, b 是用不到的, 但是在
遍歷到 c 之前,無法確定是否會出現這樣的情況。 一旦出現這樣的情
況, b 對答案無影響並且 b 可能在以後用到。
這時候考慮放進去兩個 b。
具體思路:
① 遍歷到 a,放 a;
② 遍歷到 b,發現 b 比 a 大, 將 b-a 加入答案,同時放進去兩個 b,
在優先隊列裏等待被買;
③ 如果之後找到一個 c>b, b 作爲堆頂元素被買, 將 c-b 加入答案。此
時加入的答案總和爲:(b-a) +(c-b) =c-a , b 用不到,但是 b 被
減沒了, 如果後面有 f>b, 這時放入的另一個 b 就派上了用場;
④ 將 b 放進去後,如果 b 從此以後一直是比較大的,那麼之後一定不會再以 b 價格買入, b 不會成爲堆頂, 放進去的另一個 b 就一直
用不到。
這樣, 就對每一個可以進行操作堆頂元素執行了買的操作, 對每一個
當前遍歷到的比堆頂元素大的元素執行了賣的操作。最後可能會剩下
一些賣不出去的東西, 這就相當於在股票價格爲剩下的元素時,不執
行任何操作,以上是對整個序列進行判斷比較後得到最優解的過程。
因此不需要考慮當前“持有”的股票數量以及如何使最後剩餘的股票
數爲 0 的策略。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=300000+3;
long long n,s,ans;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    scanf("%d",&n);
    scanf("%d",&s);//不能訪問空隊列的隊首所以先放進去一個
    q.push(s);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&s);
        if(s>q.top()&&!q.empty())
        {
            ans+=s-q.top();
            q.pop();
            q.push(s);
        }
        q.push(s);
    }
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章