洛谷 CF865D Buy Low Sell High(反悔贪心)

传送门


解题思路

错误思路:对于每天的股票,若比当前入手的最低价股票高,则入手前面的,并在今天卖出去,再把今天的买入,为以后做准备。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=300005;
int a[maxn],n;
long long ans;
priority_queue<int,vector<int>,greater<int> > q;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        if(!q.empty()&&q.top()<a[i]){
            ans+=a[i]-q.top();
            q.pop();
        }
        q.push(a[i]);
    }
    cout<<ans;
    return 0;
}
错误代码

 

为什么错误了呢?

我们看这一组样例:

4

1 2 4 5

我们会在第一天买入,入队1,然后第二天卖出,出队1入队2,赚1差价,然后第三天买入第二天的,再卖出,出队2入队4,赚2,然后在第四天买入第三天的再卖出,入队4出队3,赚1.

一共赚了1+2+1=4。

但是很显然可以第一天买入第三天卖出,赚3,第二天买入第四天卖出,赚3,一共赚3+3=6。

Q:差在哪里呢?

A:第二天的邮票再做中间量后其实是可以再购买的。

所以

  • 做法一:就是加一个vis的数组,表示买没买此邮票。优先队列中的变量可以改成pair。
  • 做法二:然后翻了翻题解,发现不需要vis也可,只需要对于中间量在优先队列里加入两遍。(第一遍相当于可换,第二遍相当于可买),对于非中间量加入一遍(相当于可买)。

AC代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=300005;
 7 int a[maxn],n;
 8 bool vis[maxn];
 9 long long ans;
10 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
11 int main(){
12     cin>>n;
13     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
14     for(int i=1;i<=n;i++){
15         if(!q.empty()&&q.top().first<a[i]){
16             vis[q.top().second]=!vis[q.top().second];
17             ans+=a[i]-q.top().first;
18             if(vis[q.top().second]) q.push(q.top());
19             q.pop();
20             q.push(make_pair(a[i],i));
21         }else{
22             q.push(make_pair(a[i],i));
23             vis[i]=1;
24         }
25     }
26     cout<<ans;
27     return 0;
28 }

 

posted @ 2020-11-04 23:31  尹昱钦  阅读(126)  评论(0编辑  收藏  举报