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;
}
posted on 2021-11-04 21:37  JYFHYX  阅读(34)  评论(0编辑  收藏  举报