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
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int n, c, a[N];
int sell[N], buy[N];

struct Candy {
    int num, price;
};

int main() {

    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &c);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        a[n + 1] = a[n];
        for(int i = 0; i <= n; i++) {
            scanf("%d%d", &buy[i], &sell[i]);
        }

        deque<Candy> que;
        int candytot = 0;
        LL ans = 0;

        for(int i = 0; i <= n; i++) {
            int cnt = 0;
            while(!que.empty() && que.back().price > buy[i]) {
                candytot -= que.back().num;
                ans -= 1LL * que.back().num * que.back().price;
                que.pop_back();
            }

            if(candytot != c) {
                que.push_back(Candy{c - candytot, buy[i]});
                ans += 1LL * (c - candytot) * buy[i];
                candytot = c;
            }

            while(!que.empty() && que.front().price < sell[i]) {
                candytot -= que.front().num;
                que.pop_front();
            }

            if(candytot != c) {
                que.push_front(Candy{c - candytot, sell[i]});
                candytot = c;
            }

            int dis = a[i + 1] - a[i];
            candytot -= dis;

            while(dis) {
                assert(SZ(que));
                if(dis < que.front().num) {
                    que.front().num -= dis;
                    dis = 0;
                }
                else {
                    dis -= que.front().num;
                    que.pop_front();
                }
            }

        }

        while(!que.empty()) {
            ans -= 1LL * que.back().num * que.back().price;
            que.pop_back();
        }

        printf("%lld\n", ans);
    }
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/11193168.html

时间: 2024-09-27 18:20:25

HDU - 5380 Travel with candy (看题解)的相关文章

hdu 5380 Travel with candy(双端队列)

题目链接:hdu 5380 Travel with candy 保持油箱一直处于满的状态,维护一个队列,记录当前C的油量中分别可以以多少价格退货,以及可以推货的量.每到一个位置,可以该商店的sell值更新队列中所有价格小于sell的(还没有卖).用buy值更新队列中大于buy(卖掉了).移动所消耗的油从价格最低的开始. #include <cstdio> #include <cstring> #include <algorithm> using namespace st

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 2896 病毒侵袭 AC自动机题解

本题是在text里面查找key word的增强版,因为这里有多个text. 那么就不可以简单把Trie的叶子标志记录修改成-1进行加速了,可以使用其他技术,我直接使用个vis数组记录已经访问过的节点,达到加速效果,速度还算挺快的. 不过看discuss里面有人直接使用Trie,做出了140ms的速度,而且他的程序严格来说并不正确,可见本题的数据很水啊.Trie的时间效率肯定比AC自动机低,但是在数据很水的特殊情况下,Trie的速度也可以很快的. 注意两个细节: 1 病毒也需要安装顺序输出,不小心

hdu 2433 Travel (最短路径树)

hdu 2433 Travel Description One day, Tom traveled to a country named BGM. BGM is a small country, but there are N (N <= 100) towns in it. Each town products one kind of food, the food will be transported to all the towns. In addition, the trucks will

HDU 2063 过山车 二分图题解

一个男女搭配的关系图,看可以凑成多少对,基本和最原始的一个二分图谜题一样了,就是 一个岛上可以凑成多少对夫妻的问题. 所以是典型的二分图问题. 使用匈牙利算法,写成两个函数,就非常清晰了. 本程序还带分配释放程序,当然oj一般不需要.但是好的程序一定要. #include <stdio.h> #include <stdlib.h> int K, M, N, a, b; int *linker; bool **gra, *used; void initGraph() { gra =

HDU 4760 Good FireWall 完善Trie题解

本题乍看像是线段树之类的区间操作,不过因为只是需要查找ip的前缀,故此其实是使用Trie来做. 这里的Trie使用到了Delete函数,这是个Trie函数中最难的函数了,当然要使用数组记录的方法水掉,也是可以的.这里不水,给出delete函数. 考点难点: 1 Trie的操作函数的灵活运用,主要难点是delete函数的灵活运用 2  在叶子节点所有的group id, 删除的时候要注意,不能一气删除了,有多个group id会挂在同一颗树中 3  源ip和目的ip也许在多个叶子节点中,要使用两个

HDU 1231 最大连续子序列 DP题解

典型的DP题目,增加一个额外要求,输出子序列的开始和结尾的数值. 增加一个记录方法,nothing special. 记录最终ans的时候,同时记录开始和结尾下标: 更新当前最大值sum的时候,更新开始节点. const int MAX_N = 10001; long long arr[MAX_N]; int N, sta, end; long long getMaxSubs() { long long sum = 0, ans = LLONG_MIN; int ts = 0; for (int

HDU 1160 FatMouse&#39;s Speed DP题解

本题就先排序老鼠的重量,然后查找老鼠的速度的最长递增子序列,不过因为需要按原来的标号输出,故此需要使用struct把三个信息打包起来. 查找最长递增子序列使用动态规划法,基本的一维动态规划法了. 记录路径:只需要记录后继标号,就可以逐个输出了. #include <stdio.h> #include <algorithm> using namespace std; const int MAX_N = 1005; struct MouseSpeed { int id, w, s; b