【队内胡策】洛圣都

16 篇文章 0 订阅
6 篇文章 0 订阅

【2017.10.24T3】
洛圣都,一个庞大且阳光普照的繁华都市,充满了自我救赎的大师
们,贪官污吏们和落魄的名人们, 一群被羡慕着的西方世界的居民
却也正处于挣扎着生存的时代,衰落的经济和廉价的道义让这里混
乱不堪。
题目描述
当你刚刚踏入洛圣都,就看见拉玛尔走了过来。
“哦,兄弟,见到你可真高兴。”
“来吧这里是洛圣都, 你有我罩着包你满意。”
“我们最近发现了一桩好活儿”拉玛尔无不得意的说, “我们完全掌握了一种
股票的行情, 每天只需要到买倒卖,其他的什么也不做。要来试试吗?这才是
文明人的赚钱方式。 ”
你可以在接下来的 N 天内完全预测某种股票的价格,你可以利用这个知识获
利,但每天只能处理一份股票。 也就是说,你每天要么买一份, 要么卖一份,
要么什么也不做。 最初你拥有 0 份股票,当你不拥有任何股票时,你不能出售
股票。
在 N 天结束的时候, 你需要使自己手中的股票为 0, 但希望在 N 天的过程中赚
到尽量多的钱。
输入格式
输入文件 resell.in
第一行输入一个 N 表示天数。
接下来的 N 行每行一个整数 Pi 表示第 i 天某种股票的价格。
输出格式
输出文件 resell.out
一个整数为赚到的最大金额。
样例输入 1
9
10 5 4 7 9 12 6 2 10
样例输出 1
20样例输入 2
20
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4
样例输出 2
41
数据范围及提示
数据保证结果小于 MAX_longlong
对于 30%的数据: 1<=n<=10
对于 100%的数据: 1<=n<=300000

CF上的原题。登不上去,在本地测了一下。

原题面:
E. Buy Low Sell High
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You can perfectly predict the price of a certain stock for the next N days. You would like to profit on this knowledge, but only want to transact one share of stock per day. That is, each day you will either buy one share, sell one share, or do nothing. Initially you own zero shares, and you cannot sell shares when you don’t own any. At the end of the N days you would like to again own zero shares, but want to have as much money as possible.
Input
Input begins with an integer N (2 ≤ N ≤ 3·105), the number of days.
Following this is a line with exactly N integers p1, p2, …, pN (1 ≤ pi ≤ 106). The price of one share of stock on the i-th day is given by pi.
Output
Print the maximum amount of money you can end up with at the end of N days.
Examples
input
9
10 5 4 7 9 12 6 2 10
output
20
input
20
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4
output
41
Note
In the first example, buy a share at 5, buy another at 4, sell one at 9 and another at 12. Then buy at 2 and sell at 10. The total profit is  - 5 - 4 + 9 + 12 - 2 + 10 = 20.
英文题解(思路来源)
OrzWWQ

题解

题目条件:
① : 可以在接下来的 N 天内完全预测某种股票的价格;
② :每天只能处理一份股票,要么买一份, 要么卖一份,要么什么
也不做;
③ :在 N 天结束的时候, 你需要使自己手中的股票为 0;
④ :希望在 N 天的过程中赚到尽量多的钱。
贪心。
每天给出一个股票价格,可以选择在这一天以这一价格买入或卖出。
对于第三个条件不需要考虑,只需根据后面的处理过程假设在这一天
买入或卖出, 并不需要“持有”任何股票。
显然,为了赚到更多的钱,需要在价格较低时买入,价格较高时卖出。
但是并不知道具体在哪一天是买入或卖出的最好时间。 于是维护一个小根堆。 由于卖出的只能是先前已经买入的,所以小根堆中记录当天
之前的信息。之后每加入一天的价格,将当前价格与堆顶(最小元素)
比较:
now>top, 将 now-top 加入答案;
now<=top, 将 now 放入堆。
然而这样的策略并不完美。
例如: 3, 4,7
按照以上思路, 遍历到 4 时发现 4 比 3 大就直接把 4-3 加入了答案,
实际上存在更优解: 7-3=4
观察发现 7-3=(4-3)+(7-4) 也就相当于没有用到 4
也就是说,如果只考虑 a小于b小于c 这样的子序列, b 是用不到的, 但是在
遍历到 c 之前,无法确定是否会出现这样的情况。 一旦出现这样的情
况, b 对答案无影响并且 b 可能在以后用到。
这时候考虑放进去两个 b。
具体思路:
① 遍历到 a,放 a;
② 遍历到 b,发现 b 比 a 大, 将 b-a 加入答案,同时放进去两个 b,
在优先队列里等待被买;
③ 如果之后找到一个 c>b, b 作为堆顶元素被买, 将 c-b 加入答案。此
时加入的答案总和为:(b-a) +(c-b) =c-a , b 用不到,但是 b 被
减没了, 如果后面有 f>b, 这时放入的另一个 b 就派上了用场;
④ 将 b 放进去后,如果 b 从此以后一直是比较大的,那么之后一定不会再以 b 价格买入, b 不会成为堆顶, 放进去的另一个 b 就一直
用不到。
这样, 就对每一个可以进行操作堆顶元素执行了买的操作, 对每一个
当前遍历到的比堆顶元素大的元素执行了卖的操作。最后可能会剩下
一些卖不出去的东西, 这就相当于在股票价格为剩下的元素时,不执
行任何操作,以上是对整个序列进行判断比较后得到最优解的过程。
因此不需要考虑当前“持有”的股票数量以及如何使最后剩余的股票
数为 0 的策略。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=300000+3;
long long n,s,ans;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    scanf("%d",&n);
    scanf("%d",&s);//不能访问空队列的队首所以先放进去一个
    q.push(s);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&s);
        if(s>q.top()&&!q.empty())
        {
            ans+=s-q.top();
            q.pop();
            q.push(s);
        }
        q.push(s);
    }
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值