hdu 5380 Travel with candy(双端队列)

题目链接:hdu 5380 Travel with candy

保持油箱一直处于满的状态,维护一个队列,记录当前C的油量中分别可以以多少价格退货,以及可以推货的量。每到一个位置,可以该商店的sell值更新队列中所有价格小于sell的(还没有卖)。用buy值更新队列中大于buy(卖掉了)。移动所消耗的油从价格最低的开始。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int maxn = 2 * 1e5 + 5;

ll ans;
int N, C, L, R, D[maxn], S[maxn], B[maxn], W[maxn * 2], V[maxn * 2];

void init () {
	scanf("%d%d", &N, &C);
	for (int i = 1; i <= N; i++)
		scanf("%d", &D[i]);
	for (int i = 0; i <= N; i++)
		scanf("%d%d", &B[i], &S[i]);
}

void merge(int s) {
	int v = 0;
	while (L <= R && W[L] <= s)
		v += V[L++];

	if (v) {
		W[--L] = s;
		V[L] = v;
	}
}

int sell (int s) {
	int ret = 0;
	while (L <= R && W[R] >= s) {
		ans -= 1LL * V[R] * W[R];
		ret += V[R--];
	}
	return ret;
}

void consume(int v) {
	while (v) {
		int k = min(V[L], v);
		v -= k;
		V[L] -= k;
		if (V[L] == 0)
			L++;
	}
}

void solve () {
	ans = 0;
	L = N, R = N - 1;;

	for (int i = 0; i < N; i++) {
		merge(S[i]);
		int add = (i == 0 ? C : D[i] - D[i-1]);
		add += sell(B[i]);
		W[++R] = B[i];
		V[R] = add;
		ans += 1LL * B[i] * add;
		consume(D[i+1] - D[i]);
	}
	merge(S[N]);
	while (L <= R) {
		ans -= 1LL * W[L] * V[L];
		L++;
	}
}

int main () {
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		init ();
		solve ();
		printf("%lld\n", ans);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-27 14:24:44

hdu 5380 Travel with candy(双端队列)的相关文章

HDU 5380 Travel with candy (单调队列&amp;贪心)

本文纯属原创,转载请注明出处.http://blog.csdn.net/zip_fan,谢谢. 题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5380. Travel with candy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Problem Description There are n+1 cities on

HDU 5380 Travel with candy 单调队列

链接 题解链接:http://www.cygmasot.com/index.php/2015/08/16/hdu_5380 题意: n C 一条数轴上有n+1个加油站,起点在0,终点在n.车的油箱容量为C 下面n个数字表示每个加油站距离起点的距离. 下面n+1行表示每个加油站买进和卖出一单位油的价格.油可以买也可以卖. 问开到终点的最小花费. 思路: 把油箱保持装满,然后维护一个价格单调递增的队列. #pragma comment(linker, "/STACK:1024000000,10240

HDU - 5380 Travel with candy (看题解)

HDU - 5380 感觉又是个脑洞题. 如果没有卖的情况感觉写过很多次了. 这题的关键在于你买糖的消耗只在加入队列的时候计算, 用不完的糖在最后退掉, 卖糖的盈利也包含在最后退糖中了, 我们只要把所有比当前sell值小的全部边成当前的sell值就行了, 相当于卖掉了. 感觉相当巧妙. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #defin

HDU 4286 Data Handler (双端队列)

Data Handler Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 616 Problem Description You are in charge of data in a company, so you are called "Data Handler&qu

hdu5380 贪心+双端队列

http://acm.hdu.edu.cn/showproblem.php?pid=5380 Problem Description There are n+1 cities on a line. They are labeled from city 0 to city n. Mph has to start his travel from city 0, passing city 1,2,3...n-1 in order and finally arrive city n. The dista

单调队列(双端队列) poj2823 hdoj3415 hdoj3530

单调队列及其应用(双端队列) 单调队列,望文生义,就是指队列中的元素是单调的.如:{a1,a2,a3,a4--an}满足a1<=a2<=a3--<=an,a序列便是单调递增序列.同理递减队列也是存在的. 单调队列的出现可以简化问题,队首元素便是最大(小)值,这样,选取最大(小)值的复杂度便为o(1),由于队列的性质,每个元素入队一次,出队一次,维护队列的复杂度均摊下来便是o(1). 如何维护单调队列呢,以单调递增序列为例: 1.如果队列的长度一定,先判断队首元素是否在规定范围内,如果超范

8、泛型程序设计与c++标准模板库2.3双端队列容器

双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为<deque>. 1)双端队列容器的构造函数 有4中形式的构造函数: deque();//构造size()为0的双端队列容器 deque(size_type n,const T& v=T());//初始化大小为n的双端队列,第二个参数是每个元素的初始值,默认为T()构造的对象 deque(c

习题3.26双端队列

#include<stdio.h> #include<stdlib.h> struct Node; struct Queue; typedef struct Node * PtrToNode; typedef struct Queue * PtrToQ; struct Node{ PtrToNode Pre; PtrToNode Next; ElemenType Ele; } struct Queue{ PtrToNode front; PtrToNode rear; }; Ptr

nyoj1117 鸡蛋队列 (双端队列,deque)

题目1117 题目信息 运行结果 本题排行 讨论区 鸡蛋队列 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 将两根筷子平行的放在一起,就构成了一个队列.将带有编号的鸡蛋放到两根筷子之间叫做入队(push),将筷子之间的鸡蛋拿出来叫做出队(pop).但这两种方式有特殊的定义,对于入队,只能将鸡蛋从队列的尾部向里放入:对于出队,只能将鸡蛋从队列的头部向外将鸡蛋拿出来. 将①.②入队: 头____________尾                         ___