买卖股票 反悔操作【贪心】
本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:
买卖股票
(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 }