排队时前面有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 namespace std;
using ll = long long;
const ll inf = 1e18;
#define rep(i,a,b) for(ll i=a; i<=b; i++)
#define per(i,a,b) for(ll i=b; i>=a; i--)
////////////////////////////////////////////////////
const ll N = 200005;
ll n, m, a[N], b[N], dp[N][2];
void solve() {
cin >> n >> m;
rep(i,1,n) cin >> a[i];
rep(i,1,n) cin >> b[i];
dp[n+1][0] = dp[n+1][1] = 0;
per(i,1,n) {
dp[i][0] = b[i] + min(dp[i+1][0], dp[i+1][1]);
dp[i][1] = a[i] + min(dp[i+1][0], dp[i+1][1]);
}
ll ans = inf;
rep(i,1,m) {
ans = min(ans, dp[i][1]);
}
cout << ans << "\n";
}
////////////////////////////////////////////////////
int main() {
int t = 1; cin >> t;
while (t--) solve();
return 0;
}
int myinit = []() {
cin.tie(0)->sync_with_stdio(0);
return 0;
}();
标签:cf1945D,花费,ll,插队,cin,rep,dp
From: https://www.cnblogs.com/chenfy27/p/18101338