chenfy27的刷题记录

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

统计

cf1945D 插队的最小花费

排队时前面有n个人,现在想通过插队来排进队伍前m,每次插队时可以选择前面的某个人x,与他互换位置,需要支付a[x]的费用给x,并且还要支付给中间每个人b[i]的费用。现在给定a[i]和b[i],求最小花费。
1<=m<=n<=2e5; 1<=a[i],b[i]<=1e9

分析:对于中间的某个人,要么经过他,要么跨过他,记dp[i][0]表示插队到位置i并且跨过他的最小花费,dp[i][1]表示插队到位置i并且经过他的最小花费,从后往前递推即可。

#include <bits/stdc++.h>
using i64 = long long;
const i64 inf = 1E16;
const i64 N = 200005;
i64 n, m, a[N], b[N], dp[N][2];
void solve() {
std::cin >> n >> m;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
for (int i = 1; i <= n; i++) {
std::cin >> b[i];
}
dp[n+1][0] = dp[n+1][1] = 0;
for (int i = n; i >= 1; i--) {
dp[i][0] = b[i] + std::min(dp[i+1][0], dp[i+1][1]);
dp[i][1] = a[i] + std::min(dp[i+1][0], dp[i+1][1]);
}
i64 ans = inf;
for (int i = 1; i <= m; i++) {
ans = std::min(ans, dp[i][1]);
}
std::cout << ans << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1; std::cin >> t;
while (t--) solve();
return 0;
}

posted on   chenfy27  阅读(7)  评论(0编辑  收藏  举报

点击右上角即可分享
微信分享提示