zoukankan      html  css  js  c++  java
  • AGC 007 D

    D - Shik and Game

    链接

    题意:

      数轴上有一个人,从0出发到E,速度为1。数轴上还有n只熊,每只熊会在经过后的T时刻后产生一个金币。给定E,T以及n个熊的坐标pi,求收集完所有金币并到达E的最短时间。N≤105,E,T≤109

    分析:

      首先由转移方程:$f_i = f_j + p_i - p_j + max{T,2 imes (p_i - p_{j + 1})}$

      因为一定是要走完E的距离,所以可以写成$f_i = f_j + max{T,2 imes (p_i - p_{j + 1})}$,最后加E。

      对中间的max讨论一下,$f_i = f_j + T$, $f_i = f_j + 2 imes (p_i - p_{j + 1})$,然后转移点j具有单调性,可以维护。

      后面的变成$f_i = f_j + 2 imes p_i - 2 imes p_{j + 1}$,发现对一段前缀取$f_j - 2 imes p_{j + 1}$的最小值。

      时间复杂度$O(n)$

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 1000005;
    LL f[N], p[N];
    
    int main() {
        int n = read(), E = read(), T = read();
        for (int i = 1; i <= n; ++i) p[i] = read();
        LL Mn = 1e18;
        int j = 0;
        for (int i = 1; i <= n; ++i) {
            while (j <= i && 2 * (p[i] - p[j + 1]) > T) {
                Mn = min(Mn, f[j] - 2 * p[j + 1]);
                ++ j;
            }
            if (j < i) f[i] = f[j] + T;
            f[i] = min(f[i], Mn + 2 * p[i]);
        }
        cout << f[n] + E;
        return 0;
    }
  • 相关阅读:
    SQL SERVER数据库索引(学习笔记)
    下载word文档
    Asp.net MVC 3+ Jquery UI Autocomplete实现百度效果
    利用C#实现分布式数据库查询
    SQL2005 存储过程通用分页
    发送电子邮件
    查看索引碎片,并生成重建索引代码
    数学趣题——哥德巴赫猜想的近似证明
    数学趣题——判断回文数字
    数学趣题——填数字游戏
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10334045.html
Copyright © 2011-2022 走看看