2020 ICPC沈阳H题(dp+二分)好题

TP
由于题目中出现了非常多的1e9范围的数据,所以能够拿来跑循环的一个是n(套餐种类),一个是m(每次哪天租几次),同时 ∑ q i < = 3 e 5 \sum{qi} <= 3e5 qi<=3e5也很令人在意,然后发现几乎不可能再m上直接设置状态,因为时间复杂度会变得非常不合理,所以选择在 ∑ q i \sum{qi} qi上转移,每次租车都属于某一天,那么我们可以根据相隔天数讨论,如果符合可以直接转移,否则在 ∑ q i \sum{qi} qi上二分,由于我们在开始时会对天数排序,那么越往后天数也会越大。知道我们找到一个点,这个点刚好是我们租这种车还没过期的最后一天,我们更新这一天即可,答案就是最后一天的dp值。
非常合理的dp,但是状态设置很巧妙,确实是个非常不错的思维题。

#include "bits/stdc++.h"

using namespace std;
#define int long long
#define pii  pair<int,int>
//const int INF = 1e17;
const int mod = 1e6 + 3;
const int N = 3e5;
const int MOD = 1e9 + 7;
int a[N];
struct node {
    
    
    int per, rent, cot;
} p[N];
struct use {
    
    
    int d, t;
} u[N];
int dp[N];
int to[N];
int n, m, r;
int tot = 0;
int Find(int y, int day) {
    
    
    int l = 1;
    int rr = tot;
    while (l <= rr) {
    
    
        int mid = (l + rr) >> 1;
        if (to[mid] <= day + p[y].per - 1)
            l = mid + 1;
        else
            rr = mid - 1;
    }
    return l - 1;
}


void solve() {
    
    
    cin >> n >> m >> r;
    for (int i = 1; i <= n; ++i) {
    
    
        cin >> p[i].per >> p[i].rent >> p[i].cot;
    }
    for (int i = 1; i <= m; ++i) {
    
    
        cin >> u[i].d >> u[i].t;
    }
    sort(u + 1, u + 1 + m, [&](use u1, use u2) {
    
    
        return u1.d < u2.d;
    });
    for (int i = 1; i <= m; ++i) {
    
    
        tot += u[i].t;
        for (int j = tot - u[i].t + 1; j <= tot; ++j) {
    
    
            to[j] = u[i].d;
        }
    }
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for (int i = 0; i < tot; ++i) {
    
    
        dp[i + 1] = min(dp[i + 1], dp[i] + r);
        for (int j = 1; j <= n; ++j) {
    
    
            if (i + p[j].rent <= tot && to[i + p[j].rent] <= to[i + 1] + (p[j].per - 1))
                dp[i + p[j].rent] = min(dp[i + p[j].rent], dp[i] + p[j].cot);
            else {
    
    
                int pos = Find(j, to[i+1]);
                dp[pos] = min(dp[pos], dp[i] + p[j].cot);
            }
        }
    }
    cout << dp[tot] << endl;
}

signed main() {
    
    
//    freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(0);
    solve();
}

猜你喜欢

转载自blog.csdn.net/weixin_45509601/article/details/121420466
今日推荐