【题解】P2605 [ZJOI2010]基站选址

题意

在数轴的正半轴上有 N 个坐标为整数的点,第 i 个点的位置为 Di。当且仅当在 [DiSi,Di+Si] 中存在一个被选中的点时,称点 i 被覆盖。现在可以选中 K 个点,选中第 i 个点的代价为 Ci。对于点 i,若其未被覆盖,则需要额外付出 Wi 的代价。试求代价之和的最小值。

N2×104,Kmin(102,N),Di,Si109,Ci,Wi104

思路

线段树优化 dp。

显然可以考虑一个朴素的 dp。如果设 f[i][j] 表示前 i 个点中选择 j 个点的最小代价和,则需要枚举最后一个被选中的点,时间复杂度不优。考虑设 f[i][j] 表示前 i 个点中,选择 j 个点且选择点 i 的最小代价和。

简单地,有状态转移方程:

f[i][j]=min[f[k][j1]+cost(k,i),k[1,i1]

其中 cost(k,i) 表示 [k+1,i1] 中无法被覆盖的点的代价和。

暴力求 cost(k,i) 的复杂度为 O(N),总复杂度为 O(N2K),于是考虑快速求 cost(k,i)

容易发现,对于每一个点 x,必然都存在且仅存在一个连续的区间 [lx,rx],使得从该区间中任意选择一个点都可以覆盖点 x。考虑二分预处理出该区间。

不妨考虑 i 向右移动 1 后的影响。若影响转移,由于 f[k][j1] 为定值,因此必然为 cost(k,i) 改变。对于 [k+1,i1] 中的任意一点 p,如果 k 可以覆盖 p,那么无论 i[i,n] 中取何值,p 都必然不会对 cost(k,i) 产生贡献。因此变化只有可能为 i 向右移动后,原本 [k+1,i1] 只有 i 可以覆盖的某些点无法被覆盖。

倒推回去,如果 [k+1,i1] 中存在只能被 i 覆盖而无法被 i+1 覆盖的点,令其为 x,则必然有 k<lx,rx=i。因此 i 向右移动时,我们只需要考虑每一个 rx=i 的点 x,然后令从 [f[1][j1],f[lx1][j1]] 转移的代价增加 wx,代表此时点 x 无法被覆盖即可。

我们发现上面的操作实质上是区间加法,区间求最小值,于是考虑用线段树维护。具体地,用线段树维护 f[k][j1]+cost(k,i) 的区间最小值。预处理出 f[1][i] 的答案后,从 j=2 开始枚举,每次建树时令 x 的权值为 f[x][j1],然后按照上面的过程操作。

为方便地求出答案,可以考虑在 + 位置虚拟一个点 x,不选中该点需要的代价为 +,选中该点的代价和该点可以覆盖的范围均为 0。令它处于下标 n+1,那么 min(f[n+1][k]),k[1,K] 即为答案。

时间复杂度 O(NKlogN)

代码

posted @   kymru  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-08-09 AC 自动机
2021-08-09 manacher 算法
点击右上角即可分享
微信分享提示
主题色彩