CF1566F
感觉好难。
首先,注意到点不会互相穿过,因为穿过了替换就行,意味着相对顺序不会改变。
那么一个点最多掉头一次,并且一个点的活动范围必须在其左右两个点之间。
这好像已经可以拿来 dp 了。设一个点的活动范围为 \([x-l, x+r]\),其中 \(x\) 为初始位置,则花费的代价为 \(2 \min\{l, r\} + \max\{l, r\}\)。
每一条线段都必须被覆盖到。先把没用的线段去掉,再注意到如果有重叠只用满足小的那条线段就可以了。那么现在只关注相邻的两个点和中间的很多条线段,这些线段的左端点和右端点都递增,枚举一个分界点,左边的线段用左侧的那个点覆盖,右边的线段用右边的那个点覆盖,也就是可以确定一个点的活动范围了。
那么 dp 时再记一下是否已经有那个 *2 了,枚举相邻的点确定活动范围转移。
感觉用确定范围更直观一些,用是否 *2 来表示也比先走或者先右更好一些。
#include <bits/stdc++.h>
using LL = long long;
void solve() {
int n, m; scanf("%d %d", &n, &m);
std::vector<int> a(n);
std::vector<std::pair<int, int>> p(m);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
for (auto &[x, y] : p) scanf("%d %d", &x, &y);
std::sort(a.begin(), a.end());
std::sort(p.begin(), p.end(), [&](auto x, auto y) {
return x.first != y.first ? x.first < y.first : x.second > y.second;
});
std::vector<std::pair<int, int>> b;
int mn = 1e9 + 1;
for (int i = m - 1; i >= 0; i--) {
int t = std::lower_bound(a.begin(), a.end(), p[i].first) - a.begin();
if (p[i].second >= mn) continue;
if (t != n && p[i].first <= a[t] && a[t] <= p[i].second) continue;
b.push_back(p[i]), mn = p[i].second;
}
std::reverse(b.begin(), b.end());
m = b.size();
if (!m) return printf("0\n"), void();
std::vector<std::vector<LL>> f(n, std::vector<LL>(2, 1e18));
for (int i = 0, l = 0, r = 0; i < n; i++) {
l = r;
while (r < m && b[r].second < a[i]) ++r;
if (!i) {
int disl = std::max(a[0] - b[0].second, 0);
f[i][0] = disl, f[i][1] = 2ll * disl;
continue;
}
for (int j = l; j <= r; j++) {
int disl = j == l ? 0 : b[j - 1].first - a[i - 1];
int disr = j == r ? 0 : a[i] - b[j].second;
f[i][0] = std::min({f[i][0], f[i - 1][1] + disl + disr, f[i - 1][0] + 2ll * disl + disr});
f[i][1] = std::min({f[i][1], f[i - 1][1] + disl + 2ll * disr, f[i - 1][0] + 2ll * disl + 2ll * disr});
}
}
int disr = std::max(b[m - 1].first - a[n - 1], 0);
printf("%lld\n", std::min(f[n - 1][0] + 2ll * disr, f[n - 1][1] + disr));
}
int main() {
int T; scanf("%d", &T); while (T--) {
solve();
}
}
本文来自博客园,作者:purplevine,转载请注明原文链接:https://www.cnblogs.com/purplevine/p/18911646

浙公网安备 33010602011771号