• GYM 101572A(单调队列优化dp)


    要点

    • 较好的思路解析
    • (dp[i])为到达(i)花费的最短时间,(dis[i]-dis[j]<=lim1)的情况其实可以省略,因为就相当于没买咖啡,绝对不优于在那之前的某店买了咖啡并发挥效用;(lim1<dis[i]-dis[j]<lim0)可以用一个队列维护在范围内的点,用单增的队列就可以之间取队头,注意维护时相等也要入队,因为往后滑动窗口时如果第一个被淘汰了,第二个却可能合法;(dis[i]-dis[j]>=lim0),因为是从头开始在距离上都合法所以不需要队列滑动,只要用变量维护最值即可。
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    typedef double db;
    const int maxn = 5e5 + 5;
    const db eps = 1e-8;
    
    ll L;
    int a, b, t, r, n;
    int pre[maxn];
    ll dis[maxn];
    db dp[maxn];
    db val[maxn];
    
    int dcmp(db x) {
    	if (fabs(x) < eps)	return 0;
    	return x > 0 ? 1 : -1;
    }
    
    void print(int i, int cnt) {
    	if (!i) {
    		cout << cnt << '
    ';
    		return;
    	}
    	print(pre[i], cnt + 1);
    	cout << i - 1 << " ";
    }
    
    int main() {
    	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    	cin >> L >> a >> b >> t >> r >> n;
    	for (int i = 1; i <= n; i++) {
    		cin >> dis[i];
    	}
    	dis[++n] = L;
    
    	ll lim0 = t * a + r * b;
    	ll lim1 = t * a;
    	int j = 1, k = 1;
    	db rej = 1e18;
    	int idj = 0;
    	int Q[maxn], head = 1, tail = 0;
    
    	for (int i = 1; i <= n; i++) {
    		dp[i] = (db)dis[i] / a;
    
    		while (j < i && dis[i] - dis[j] >= lim0) {
    			db tmp = dp[j] - (db)dis[j] / a;
    			if (dcmp(tmp - rej) < 0) {
    				rej = tmp;
    				idj = j;
    			}
    			j++;
    		}
    		if (idj) {
    			db tmp = rej + (db)(dis[i] - lim0) / a + t + r;
    			if (dcmp(dp[i] - tmp) > 0) {
    				dp[i] = tmp;
    				pre[i] = idj;
    			}
    		}
    
    		while (k < i && dis[i] - dis[k] >= lim1) {
    			val[k] = dp[k] - (db)dis[k] / b;
    			while (head <= tail && dcmp(val[Q[tail]] - val[k]) > 0)	tail--;
    			Q[++tail] = k++;
    		}
    		while (head <= tail && dis[i] - dis[Q[head]] >= lim0)	head++;
    		if (head <= tail) {
    			db tmp = val[Q[head]] + (db)(dis[i] - lim1) / b + t;
    			if (dcmp(dp[i] - tmp) > 0) {
    				dp[i] = tmp;
    				pre[i] = Q[head];
    			}
    		}
    	}
    	
    	print(pre[n], 0);
    }
    
  • 相关阅读:
    js4——字符转化
    js3——表格下拉
    笔记展现
    js2——定时跳转
    js学习——1
    明明在/etc/my.cnf 配置了mysql.sock,为什么会在/var/lib/mysql/mysql.sock 里边寻找
    RBAC用户权限管理数据库设计
    mysql 字节问题,中文和数字
    PHP闭包
    一致性哈希算法原理
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10917784.html
Copyright © 2020-2023  润新知