买卖股票 反悔操作【贪心】

本人水平有限,题解不到为处,请多多谅解

本蒟蒻谢谢大家观看

题目

买卖股票
(stack.cpp/in/out 1s 512M)
已知接下来N天的股票价格,每天你可以买进一股股票,卖出一股股票,或者什么也不做.N天之后你拥有的股票应为0,当然,希望这N天内能够赚足够多的钱.
Input
第一行一个整数天数N(2<=N<=300000).
第二行N个数字p1,p2...pN(1<=pi<=10^6),表示每天的价格.
Output
 N天结束后能获得的最大利润.
Sample Input
3
1 2 5
Sample Output
4

本题是一道经典的贪心题,带有反悔操作

先解释一下什么是反悔操作

反悔操作:

先是true,之后发现要改,我们就修改为false,类似于你今天如果买彩票可以中10^10的大奖,但是你错过了,没有买。为此你非常后悔,想时间倒流来进行反悔操作。

那样例来说:

我们发现2>1,所以先购买第一天的股票,在第二天卖出,此时差价为(2-1)==1,也就是赚的钱为1;

然后我们发现5又大于2,所以我们又购买第二天的股票,在第三天卖出,此时差价为(5-2)==3,也就是赚的钱为3,最后统计答案:1+3==4,ans==4

观察上述式子可以发现2用了两次,一次卖,一次买;也就相当于反悔操作(一买一卖刚好抵消),等于我们在第二天什么也不做。

用小根堆来维护一个单调递增序列,在队首不断操作

code:

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(3)
 3 #define int long long
 4 const int N=3e5+100;
 5 using namespace std;
 6 priority_queue<long long,vector<long long >,greater<long long > > q; 
 7 int n,a[N];
 8 int ans;
 9 inline int read(){
10     int x=0,f=1;char ch=getchar();
11     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
12     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
13     return x*f;
14 }
15 inline void write(int x){
16      char F[200];
17      int tmp=x>0?x:-x ;
18      if(x<0)putchar('-') ;
19      int cnt=0 ;
20         while(tmp>0)
21         {
22             F[cnt++]=tmp%10+'0';
23             tmp/=10;
24         }
25         while(cnt>0)putchar(F[--cnt]) ;
26 }
27 signed main()
28 {
29     n=read();
30     for(int i=1;i<=n;i++){
31         a[i]=read();
32         q.push(a[i]);
33         if(!q.empty()&&q.top()<a[i]){
34             ans+=a[i]-q.top();
35             q.pop();
36             q.push(a[i]);
37         }
38     }
39     printf("%lld\n",ans);
40     return 0;
41 }

猜你喜欢

转载自www.cnblogs.com/nlyzl/p/11694912.html