CF1106E Lunar New Year and Red Envelopes

这题比较容易看出来是dp,但是不容易看出来的一点是,如果当前点我们能够选,那么只要在这个范围内的可行答案我们都可以挑选,这是因为

s<t<d,如果当前点可以选,那么不会存在之前选过这些点,因为一旦选过,当前点就不能选。所以我们用优先队列预处理一下当前点选啥

之后dp求取即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
const int N=1e5+10;
const int M=2e6+10;
const int inf=0x3f3f3f3f;
const int mod=772002;
int n,m,k;
struct node{
    ll s,t,d,w;
    bool operator <(const node &t) const{
        if(w==t.w)
            return d<t.d;
        return w<t.w;
    }
}g[N];
ll f[N][205];
int times[N];
int v[N];
priority_queue<node> q;
bool cmp(node a,node b){
    return a.s<b.s;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    int i;
    for(i=1;i<=k;i++){
        cin>>g[i].s>>g[i].t>>g[i].d>>g[i].w;
    }
    sort(g+1,g+1+k,cmp);
    int cur=1;
    times[0]=1;
    for(int i = 1; i <= n; ++i) {
        while(cur <= k && g[cur].s <= i)
            q.push(g[cur++]);
        if(q.empty()) times[i] = i+1;
        else {
            node u = q.top();
            if(u.t < i) {
                --i;
                q.pop();
                continue;
            }
            times[i] = u.d+1;
            v[i] = u.w;
        }
    }
    memset(f,0x3f,sizeof f);
    f[0][0]=0;
    for(int i = 0; i <= n; ++i)
    for(int j = 0; j <= m; ++j) {
        f[i+1][j+1] = min(f[i+1][j+1], f[i][j]);
        f[times[i]][j] = min(f[times[i]][j], f[i][j] + v[i]);
    }
    ll ans=1e18;
    for(i=0;i<=m;i++){
        ans=min(ans,1ll*f[n+1][i]);
    }

    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2020-09-02 20:32  朝暮不思  阅读(171)  评论(0编辑  收藏  举报