题解 CF1106E Lunar New Year and Red Envelopes
小清新 DP 题。
定义 表示在时刻 ,干扰了 次,最小贡献。
定义 表示在时刻 会收集哪个红包。
那么转移方程为:
其中,,。 为选完编号为 的红包后会跳到那个位置。
现在考虑如何预处理出 。
可以先以 为第一关键字, 为第二关键字从大到小排序。
然后将区间 中的 全部标记为当前编号,之后不再访问。
这里可以用并查集维护已经访问过的区间,遇到访问过的直接查询并查集跳过去即可。
复杂度 。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+5,N2=200+5,inf=LLONG_MAX>>1;
int n,m,k,vis[N],nex[N],fa[N];
ll f[N][N2];
struct node{int s,t,d;ll w;}a[N];
bool cmp(node x,node y){return x.w!=y.w?x.w>y.w:x.d>y.d;}
int ff(int x){return fa[x]==x?x:fa[x]=ff(fa[x]);}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=k;++i)cin>>a[i].s>>a[i].t>>a[i].d>>a[i].w;
sort(a+1,a+k+1,cmp);
for(int i=1;i<=n+1;++i)fa[i]=i;
for(int i=1;i<=k;++i){
int j=a[i].s;
while(j<=a[i].t){
if(vis[j])j=ff(j);
else {
vis[j]=1;
nex[j]=i;
fa[ff(j)]=ff(j+1);
++j;
}
}
}
for(int i=1;i<=n+1;++i)for(int j=0;j<=m;++j)f[i][j]=inf;
f[1][0]=0;
for(int i=1;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(nex[i])f[a[nex[i]].d+1][j]=min(f[a[nex[i]].d+1][j],f[i][j]+a[nex[i]].w);
else f[i+1][j]=min(f[i+1][j],f[i][j]);
}
}
ll ans=inf;
for(int j=0;j<=m;++j)ans=min(ans,f[n+1][j]);
cout<<ans<<endl;
return 0;
}
本文作者:HQJ2007
本文链接:https://www.cnblogs.com/HQJ2007/p/17561362.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端