cf1945D 插隊的最小花費

chenfy27發表於2024-03-28

排隊時前面有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;
    }();

相關文章