题意:

有n+1个城市按顺序分布在同一直线上,现在需从0号城市按顺序走到n号城市(保证可达),从0号城市到i号城市需要消耗ai个糖果,每个城市都可以通过买/卖糖果来赚取更多的钱,价格分别是buyi和selli,保证selli<buyi。由于身上最多只能带C个糖果,且在起点0号城市时身上是没有钱的,问到达n号城市的最小花费(可以是负数,即亏损)?

思路:

(1)每次离开i城市时,将C补满,并记录身上每个糖果的购买价(因为钱是可以负的,所以一定可以补满)。

(2)每次到达i城市时,先用最便宜的糖果作为路上的固定消耗。

(3)卖出糖果挣钱,并以卖价继续持有它(比较难想到的点)。

(4)"退"掉不挣钱的糖果,注意是退不是卖,即按原价退掉,就当作从未买过这些糖果(这是每次都将C补满的原因)。

  问题在于怎么知道在哪个城市卖掉比较划算?

  因为selli<buyi,所以在同城市按sell卖出后再按buy买入来补满C是不划算的,会亏了中间的差价。我们得在后面的城市根据价格,来决策前面的城市该不该卖糖果。那么将可卖的糖果卖出后,以卖价s继续买入,会有两种情况:

  1、后面卖出可以赚更多。

    之前卖s价所带来利润已经到手,所以后面卖出有赚也是可以保证利润的。

  2、后面卖出会亏。

    按s价(这是当时新买入价)退掉这些糖果,就相当于在当时就卖掉了。

#include <bits/stdc++.h>
#define max(X,Y) ((X) > (Y) ? (X) : (Y))
#define min(X,Y) ((X) < (Y) ? (X) : (Y))
#define pii pair<int,int>
#define INF 0x7f7f7f7f
#define LL long long
using namespace std;
const int N=;
int n;
LL dis[N], buy[N], sell[N], cap;
struct node
{
LL price;
int cnt;
node(){};
node(LL p, int c):price(p),cnt(c){};
}; LL cal()
{
deque<node> que(,node( buy[], cap) ); //当前持有。
LL ans=cap*buy[]; //最小费用,补满。 for(int i=; i<=n; i++)
{
LL tmp=dis[i]-dis[i-]; //手续费
LL sum=cap-tmp; //持有量。 for(; !que.empty(); que.pop_front()) //路上消耗最便宜的糖果。
{
node &t=que.front();
if(t.cnt>tmp)
{
t.cnt-=tmp;
break;
}
tmp-=que.front().cnt;
} //看能否卖掉一些。
LL cnt=;
for(; !que.empty(); que.pop_front())
{
node &t=que.front();
if(t.price>sell[i]) break;
cnt+=t.cnt;
}
if(cnt) que.push_front(node(sell[i], cnt)); //以sell价继续买入。 //看能否退掉一些:这里买比前面的还便宜,不如不带过来,那就按原价退
for( ; !que.empty(); que.pop_back())
{
node &t=que.back();
if(t.price<buy[i]) break;
ans-=t.price*t.cnt;
sum-=t.cnt; //当前持有量减少。
} que.push_back( node(buy[i], cap-sum) ); //补满!
ans+= (cap-sum)*buy[i];
}
while(!que.empty()) //按原价退,相当于从未买过这些
{
node &t=que.front();que.pop_front();
ans-=t.price*t.cnt;
}
return ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t;
cin>>t;
while(t--)
{
scanf("%d%d", &n, &cap);
for(int i=; i<=n; i++) scanf("%lld", &dis[i]);
for(int i=; i<=n; i++) scanf("%lld %lld", &buy[i], &sell[i]);
printf("%lld\n",cal());
}
return ;
}

最新文章

  1. java发送内嵌图片邮件
  2. 如何用inno setup打包activex
  3. MySQL 错误
  4. 利用 libiconv 实现汉字编码 utf-8 格式 和 gbk格式的相互转换
  5. 【BZOJ 3190】 3190: [JLOI2013]赛车 (半平面交)
  6. POJ 3047 Fibonacci
  7. jQuery实现返回顶部功能
  8. 除trigger()方法外的jquery手动触发事件
  9. python 集合相关操作
  10. 简单Elixir游戏服设计-创建玩家模型
  11. canvas三环加载进度条
  12. 设备指纹识别之User Agent 解析
  13. hiredis异步接口封装并导出到Lua
  14. nasm中的表达式
  15. 深圳市共创力推出《以用户为中心的设计UCD方法与实战》课程!
  16. face detection[Face R-CNN]
  17. 搭建vue脚手架---vue-cli
  18. 【python】python彻底卸载的方法【windows安装版卸载的示例】
  19. IOS Devices Version
  20. C#中通过Lambda表达式为委托传入更多的参数

热门文章

  1. Luogu网校听课笔记(自用
  2. 【Codeforces 632D】 Longest Subsequence
  3. 堆、栈的区别 &lt;转载&gt;
  4. Not enough free disk space on disk &#39;/boot&#39;(转载)
  5. Django View类的解析
  6. 洛谷 - P1141 - 01迷宫 - dfs
  7. HDU 6092:Rikka with Subset(dp)
  8. 用动态链表high-poj 1528
  9. 天空盒的制作方法 Max来生成天空盒的六张图片
  10. python __builtins__ str类 (65)