嘘~ 正在从服务器偷取页面 . . .

模拟赛题讲解[18]


模拟赛题讲解[18]

来自 yukuai26 2022-08-08 noi.ac #2773

题目背景

搞个大新闻. jpg

题目描述

你来到了幻想乡。首先你准备搞一个大新闻,获得文文的报道并变得出名,你决定对幻想乡的股票系统下手。

你通过猪脚光环了解到了接下来 $n$ 天的股票价格 $a_i$,你每天可以买一个股票或卖出一个股票或者什么都不做,一天只能干一件事。

那么为了搞个大事情,你希望赚的钱最多,那么你最多能获得多少钱呢? (注意到最终手上的股票不能算钱, 并且你可以暂时亏损)

输入格式

第一行一个整数 $n$,表示天数

接下来一行 $n$ 个数,表示每天股票的价格

输出格式

一行一个数,表示最大能挣的钱

输入1

9
10 5 4 7 9 12 6 2 10

输出1

20

输入2

20
3 1 8 1 7 9 5 6 5 3 5 8 2 7 9 3 2 3 8 4

输出2

41

数据范围

打包测试

测试包 1: $n \leq 15,~55$ 分

测试包 2: $n \leq 100,~a_i \leq 100 ,~10$分

测试包 3: $n \leq 5000 ,~20$分

测试包 4: $a_i \leq a_{i+1} ,~10$分

测试包 5: 无特殊限制 $5$ 分

对于 $100\%$ 的数据 $1 \leq a_i \leq 10^6,1 \leq n \leq 3\times 10^5$

题解

好可怕的贪心!QAQ

样例一某种程度上提示了我们,如何选择更好的一天卖出很重要

而很多时候我们只是不知道之后还有更好的机会卖出,显然反悔型贪心。

倒着考虑每天,维护一个可以卖的时候的大根堆

对于每个数 $a_i$ ,如果它比堆顶小,则把堆顶 $a_k$ 踢掉,代表在这一天买了股票,在堆顶卖出

并且, $a_i$ 也要入堆,因为不一定这一天买是最优的

当 $a_i$ 入堆以后,在未来某次决策中

如果有一个数 $a_j$ 加入,并踢掉了 $a_i$

这就等价于在 $a_j$ 买入, $a_i$ 卖出,再在 $a_i$ 买入,再在之前那个 $a_k$ 卖出

加粗的部分在实际决策时是不会做的,这个决策最后就等价于 $a_j$ 买 $a_k$ 卖

值得注意的时,此时我们还要把 $a_i$ 入堆,因为它也可以卖东西了(这个在代码里用 $\text{vis}$ 数组标记)

然后这题就搞定了,好难啊

时间复杂度 $O(n\log n)$

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <random>
#include <queue>
#include <bitset>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(3e5+15)

bitset<N> vis;
int n,res,a[N];
struct cmp{bool operator()(int x,int y){return a[x]<a[y];}};
priority_queue<int,vector<int>,cmp> q;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1; i<=n; i++)
        cin >> a[i];
    for(int i=n; i>=1; i--)
    {
        if(!q.empty())
        {
            int x=q.top();
            if(a[i]<a[x])
            {
                q.pop(); res+=a[x]-a[i];
                q.push(i); vis[i]=1;
                if(vis[x]) vis[x]=0,q.push(x);
            }else q.push(i);
        }else q.push(i);
    }
    cout << res << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录