• [HG]走夜路 题解


    前言

    整个机房就我一个人在想动态规划。
    想了半天发现一堆性质,结果由于DP中出现折线挂了。

    题目描述

    某NOIP普及组原题加强版
    (Jim) 非常怕黑,他有一个手电筒,设手电筒的电量上限为 (T)
    (Jim) 回家的路上有 ((N + 1)) 个充电站, (0) 是起点 (N) 是终点,
    (Jim) 每走一个单位距离消耗一个单位的电量。
    给出每个充电站到下一个充电站的距离 (D) ,以及冲单位电量的花费 (P) ,求整个旅途的最少花费。
    P.S. 如果 (Jim) 无法保证全程 手电筒都亮着输出 (-1)

    题解

    有一个美妙的贪心。
    对于当前 (Jim) 所在的点,
    如果能走到 (P) 值比它小的充电站,就适量地充电并走到它,使走到第一个 (P) 值小于他的充电站时花费的钱最小;
    如果走不到或找不到这样一个点就充满电,走到下一个充电站。
    那么怎么找到第一个 (P) 值小于它的点呢,简单第使用二分加ST表即可。
    时间复杂度为 (Theta(n logn))

    代码

    #include <cstdio>
    #define int long long
    
    int st[500005][26];
    int lg2[500005];
    int d[500005], p[500005];
    
    #define min(a,b) ((a<b)?a:b)
    
    void init(int n){
        lg2[1] = 0, lg2[2] = 1;
        for (int i = 3; i <= n; ++i)
            lg2[i] = lg2[i >> 1] + 1;
        for (int i = 1; i <= n; ++i)
            st[i][0] = p[i];
        for (int i = 1; i <= 25; ++i){
            int lim = n - (1 << i) + 1;
            for (int j = 1; j <= lim; ++j)
                st[j][i] = min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);
        }
    }
    
    inline int query(int l, int r){
        int i = lg2[r - l + 1];
        return min(st[l][i], st[r - (1 << i) + 1][i]);
    }
    
    #define max(a,b) ((a>b)?a:b)
    
    signed main(){
        int n, t; scanf("%lld %lld", &n, &t);
        for (int i = 1; i <= n; ++i)
            scanf("%lld %lld", &d[i], &p[i - 1]), d[i] += d[i - 1];
        init(n);
        int pos = 0, eng = 0, cst = 0;
        while (pos < n){
            if (eng < 0){
                puts("-1");
                return 0;
            }
            int l = pos + 1, r = n, res = -1;
            while (l <= r){
                int mid = l + r >> 1;
                if (query(pos + 1, mid) <= p[pos]) r = mid - 1, res = mid;
                else l = mid + 1;
            }
            if (d[res] - d[pos] > t){
                cst += (t - eng) * p[pos];
                eng = t - (d[pos + 1] - d[pos]);
                pos++;
            }
            else{
                int tag = 0;
                if (eng > d[res] - d[pos]) tag = eng - d[res] + d[pos];
                cst += (d[res] - d[pos] - min(eng, d[res] - d[pos])) * p[pos];
                eng = tag; pos = res;
            }
        }
        printf("%lld", cst);
        return 0;
    }
    
  • 相关阅读:
    502 bad gateway错误的网关
    nodejs发展
    edgejs
    websocket nodejs实例
    nodejs原码
    node案例
    node 与php整合
    node c#
    jquery
    express
  • 原文地址:https://www.cnblogs.com/linzhengmin/p/11765081.html
Copyright © 2020-2023  润新知