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

Posted alphawa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 << '\n';
        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);
}

以上是关于GYM 101572A(单调队列优化dp)的主要内容,如果未能解决你的问题,请参考以下文章

Gym - 101981B Tournament (WQS二分+单调性优化dp)

单调队列以及单调队列优化DP

单调队列优化dp

POJ2373 Dividing the Path(单调队列优化dp)

单调队列优化DP

bzoj2442&&codevs4654 单调队列优化dp