CF1106E Lunar New Year and Red Envelopes
由于这个题里面\(d_{i}\)是大于等于\(t_{i}\)的,那么显然每一秒\(Bob\)要拿走的那个红包显然是一定的
那么我们先处理出来每个时刻\(Bob\)要拿掉的那个红包再进行其他操作
考虑如何处理,首先按照\(s_{i}\)排个序,然后就可以用优先队列+单调指针来做了(线段树也可以)
然后处理出来这个之后就会有一个比较好想到的\(DP\)
我们设\(f_{i,j}\)为\(Alice\)干扰了\(i\)次,到第\(j\)秒的时候\(Bob\)所能拿到的最少红包的价值
那么转移的话应该就比较简单了
\(f_{i+1,j+1}=min(f_{i+1,j+1},f_{i,j})\)在第\(j+1\)秒干扰\(Bob\)
如果这以秒有红包可以拿那么就有\(f_{i,d+1}=min(f_{i,d+1},f_{i,j}+w)\)
否则的话就是\(f_{i,j+1}=min(f_{i,j+1},f_{i,j})\)
答案就是\(min(f_{i,n})\)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int maxn=1e5+5;
const int maxm=205;
struct redbag{
int s,t,d,w;
friend bool operator <(redbag a, redbag b){
return a.w>b.w||(a.w==b.w&&a.d>b.d);
}
friend bool operator >(redbag a,redbag b){
return b<a;
}
}a[maxn];
inline bool cmp(redbag a,redbag b){return a.s<b.s;}
priority_queue<redbag, vector<redbag>, greater<redbag>> q;
int n,m,k;ll ans;
int d[maxn],w[maxn];ll f[maxn][maxm];
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=k;i++)
a[i].s=read(),a[i].t=read(),a[i].d=read(),a[i].w=read();
sort(a+1,a+k+1,cmp);
for(int i=1,j=0;i<=n;i++)
{
while(j<k&&a[j+1].s<=i)q.push(a[++j]);
while(!q.empty()&&q.top().t<i)q.pop();
if(!q.empty())d[i]=q.top().d,w[i]=q.top().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]);
if(d[i]) f[d[i]+1][j]=min(f[d[i]+1][j],f[i][j]+w[i]);
else f[i+1][j]=min(f[i+1][j],f[i][j]);
}
}
ans=2e18;
for(int i=0;i<=m;i++) ans=min(ans,f[n+1][i]);
printf("%lld\n",ans);
return 0;
}