首先先感谢董哥和嘉琦学姐的良心(毒瘤)题,以及即将去考研的fuls让我有能写第一条博客的机会。
切入正题,我们先看题目:
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
题意:这就是个股票买卖问题。就是假设你很牛逼,可以预知未来n天的股票走势,但是你只能一天买一支或者卖一支股票,并且最后你手里要没有股票,假设你有无限多的钱,请问你能够得到的利润的多少。
思路:
刚开始拿到这道题,我被良心这两个字骗了,以为这就是道暴力题。于是开始就直接上手两个for,寻找a[j]-a[i]的最大值,累加到ans,然后把a[j]和a[i]存入浮点数(下次就不会访问这两个数了),然后就是很自然的,tle了。
本着一颗做不出来就给毒瘤出题人寄刀片的心,为了节省我的刀片,我翻开了c++从入门到精通(放弃),经过了60多页的搜索,我终于在第314页找到的想要的容器适配器priority_queue,作用是排列自身对象,将最大值放在队伍最前列。
为什么选用这个容器,而不用queue,因为这个题目的难点在于股票是必须先买后卖的,并且手中可以拥有多支股票,直接使用queue连第二个样例都过不了
于是我就有了思路2:
我们把a放入优先队列里,然后遇到有收益的b时(不一定是最优解),将收益(b-a)先放入ans中,然后将a弹出来(pop()),将b放入优先队列两次,让后再遇到c时将b拿出来,那收益就是(c-b)放入ans,此时ans=(b-a)+(c-b)=(c-a),这里的b就充当了一个跳板,以此类推就能找到最优解。
AC代码:
#include <queue>
#include <cstring>
#include <cstdio>
#include<cmath>
using namespace std;
priority_queue<int>st; //我寻你千百度
int main(){
int n;
long long a;
long long ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++) {
scanf("%lld",&a);
if(!st.empty()&&abs(st.top())<a)
{
ans=ans+(a-abs(st.top()));
st.pop();
st.push(-a);
st.push(-a);
}
else {
st.push(-a);
}
}
printf("%lld",ans); //学业不精告辞
}