zoukankan      html  css  js  c++  java
  • CF865D Buy Low Sell High

    题意翻译

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

    题解

    非常经典的贪心问题

    用一个优先队列小根堆。

    假设每个股票都买入。

    当前的股票价格>堆顶的时候,把这个股票加进去两次。然后弹出堆顶。

    否则加进去一次。

    把这个差价计入ans,ans+=price[i]-q.top()

    什么意义呢?

    首先,我们虽然假设都买入,但是并不一定都买。

    我们只有在计算差价的时候,相当于才会把某个价格买入,再以price[i]卖出。

    而我们把这个股票加进去两次,

    一次是正常的假设买入。为了之后可能赚取差价。

    另一次是为了反悔。

    假设股票价格是:3 7 10

    最优解是3买入,10卖出,赚7元

    也就是说,我以3价格买入,但我会在7元的时候卖出。

    但是7元卖可能不是最优秀的。

    所以,我们把7元再加进去,当轮到10元的时候,这个7元会再当做一个股票卖出ans+=10-7

    发现,有意思的是,10-3=(10-7)+(7-3)

    这就相当于3元买入,10元卖出。7元这天摸鱼。

    如果10后面假设还有一个20

    即3,7,10,20

    那么,我们10元之后,队列里有7,10,10

    20元会7元买入,20元卖出。相当于7元这天买入了一股。

    这样下去,我们总能把最少的价格买入,尽量多的价格卖出。

    如果不是最优秀的话,就不买不卖了。就是最后优先队列里剩下的一些。就是预定买入,但是实际没有买入的部分。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=300000+10;
    int n;
    int p[N];
    priority_queue<int,vector<int>,greater<int> >q;
    long long ans;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&p[i]);
            q.push(p[i]);
            if(!q.empty()&&q.top()<p[i]){
                ans+=p[i]-q.top();
                q.pop();
                q.push(p[i]);
            }
            
        }printf("%lld",ans);return 0;
    }

    总结:

    反悔堆的比较厉害的应用了。

    利用差价的关系,直接处理。

    怎么想到的?
    首先要想到贪心,然后这个题肯定要用一个反悔堆之类。

    那么,我们假设先买入,还是先都不买?

    都不买太被动。

    那就都买入,然后结算的时候,再真实买入。

    但是对于不是最优的抛售天怎么办?

    利用差价。即可。

  • 相关阅读:
    Linux(Centos)安装图形化界面步骤
    Delphi 取得桌面文件夹的路径和取得我的文档的路径
    Nginx [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use)
    待查消息
    WM_SETFOCUS和WM_KILLFOCUS、WM_GETDLGCODE、CM_ENTER...
    WM_SIZE
    MongoDB 开启与关闭
    log4j 日志文件路径
    wamp中修改配置支持多站点
    java 下载示例
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9686577.html
Copyright © 2011-2022 走看看