这题比较容易看出来是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; }