题目链接:
http://172.25.37.251/problem/22
题目大意:
第 i i i天可以以 v [ i ] v[i] v[i]的价格买进或卖出一只股票,或者什么也不干,求出能够获得的最大利益。
题目分析:
1.观察数据范围我们可以发现,这是一个
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的题,由于题目问题,排除二分的可能,那就只剩下数据结构了。
2.我们可以发现如果我以
a
a
a买进一只股票,然后以
b
b
b卖出,或者以
a
a
a买进一只股票,然后以
c
c
c卖出
(
b
<
c
)
(b<c)
(b<c),那么显然对于
a
a
a来说在
c
c
c的时候卖合适。但是由于复杂的相关性问题,导致我们不能无脑找到差值最大的两天来操作。
3.我们发现假如以
a
a
a买进一只股票,然后以
c
c
c卖出,和以
a
a
a买进一只股票,然后以
b
b
b卖出,以
b
b
b买进一只股票然后以
c
c
c卖出是一样的,所以我们开始可以尽量卖,反正在后面是可以通过替换来使答案更大的,如何保证每次替换都是最优的操作呢?那就是每次处理掉前面最小的就行(维护一个堆啊)。
正解程序:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
const ll maxn=100010;
ll n,Pri[maxn];
int main()
{
ll T=0;
while(scanf("%lld",&n)!=EOF)
{
multiset<ll> s;
T++;
ll ans=0;
for(ll i=1;i<=n;i++)
{
scanf("%lld",&Pri[i]);
if(!s.empty())
{
multiset<ll>::iterator top=s.begin();
if(Pri[i]>(*top))
{
s.erase(top);
ans=ans+Pri[i]-(*top);
s.insert(Pri[i]);
s.insert(Pri[i]);
}
else
s.insert(Pri[i]);
}
else if(i==1)
s.insert(Pri[i]);
}
printf("Case #%lld: %lld\n",T,ans);
}
return 0;
}