DP 凸优化

DP 凸优化

wqs 二分

wqs 二分主要用来处理一类恰好选 k 个的问题,这类题目若不限制选的个数,那么很容易求出最优方案。

使用前提:原问题具有凸性。设 gi 表示选 i 个物品的答案,那么所有 (i,gi) 点组成一个凸包,满足 g(k) 单调。

先不考虑恰好选 k 个的限制,考虑二分附加权值。判定是每选一个就减去附加权值,则选取的次数越多,附加权值影响越大,进而影响选的数量。根据选的数量来调整 mid ,最后调整到恰好选 k 个时减掉 k 倍的附加权值即为答案。

本质就是二分斜率,使得凸包切线切点在 x=k 处,检查函数返回的是截距。

可能出现一条切线切多个点的情况,此时就会出现 mid 时切到的 x 坐标小于 k ,而 mid+1 时切到的 x 坐标大于 k 。因此最后要减掉的是 k 倍的附加权值。

实现时每次判定时能选就选,这样就会切到最右边的点,此时为了让斜线的斜率逼近 g(k) ,于是就要根据凸壳形状减小(下凸壳)或增大(上凸壳)切线斜率,并更新答案。

P5633 最小度限制生成树

给定一张无向图,求 degs=k 的情况下的最小生成树,或报告无解。

n5×104m5×105k100

二分附加权值 mid ,与 s 连接的边的边权都减去这个 mid ,则最终MST中与 s 连接的边的数量受 mid 影响,于是可以调整使得最终 degs=k

时间复杂度 O(mlogmlogV)

P2619 [国家集训队] Tree I 做法也是类似的,把附加权值放在白色边上即可。

P4983 忘情

定义一段序列 alr 的价值为:

((i=lrai)+1)2

a1n 分为 m 段,求每段价值和的最小值。

n105

首先由于 (a+b)2a2+b2 ,所以要分的段数要越多越好,答案关于 m 增加而减小。且因为先选减小值更小的地方分开更优,具有凸性。

于是可以 wqs 二分,判定部分可以斜率优化,注意斜率优化的判断要加入选取数量为第二关键字,尽量多选。

时间复杂度 O(nlogV)

CF802O April Fools' Problem (hard)

n 道题,第 i 天可以:

  • 花费 ai 准备一道题,上限一次。
  • 花费 bi 打印一道题,上限一次。

二者可以同时选择,准备的题可以留到以后打印。

求准备并打印 k 道题的最小花费。

kn5×105

若不考虑 k 的限制,则是一道反悔贪心模板。

加入 k 的限制后,只要在外面套一个 wqs 二分即可。

CF739E Gosha is hunting

现有 n 只神奇宝贝,你有 a 个宝贝球和 b 个超级球,宝贝球抓到第 i 只神奇宝贝的概率是 pi,超级球抓到的概率则是 ui

不能在同一只神奇宝贝上使用超过一个同种球,但是可以往同一只上既使用宝贝球又使用超级球(都抓到算一个)。

求合理分配下抓到神奇宝贝的总个数期望的最大值。

n2000

首先球全部用完一定最优。考虑 wqs 二分斜率 λ ,每用一个超级球答案就减去 λ ,DP 出超级球选 b 个的方案。

直接 DP 是 O(n2logV) 的,但是可以进一步优化,考虑每个位置的四种选择:

  • 用宝贝球和超级球:p+upuλ
  • 用宝贝球:p
  • 用超级球: uλ
  • 不用球:0

先钦定所有位置都不用宝贝球,考虑一个位置从不用宝贝球到用宝贝球,答案增加量就是:

max(p+upuλ,p)max(uλ,0)

对这个增加量排序后贪心即可,时间复杂度 O(nlognlogV)

P4383 【八省联考2018】林克卡特树

给定一棵 n 个点的树,边带权。在树上选出 k+1 条互不相交链,最大化权值和。

n3×105

根据 wqs 二分的经典套路,二分斜率 λ ,下面考虑没有 k 的限制怎么做。

fu,0/1/2 表示考虑到 udegu=0/1/2 时的答案,具体的:

  • deg=0 :这个点没有连边。
  • deg=1 :这个点连着一条未完成的链,该链还未计入答案。
  • deg=2 :这个点连着一条连接两个不同子树的链。

首先约定在每个节点的全部转移结束时,进行一次更新:

gu=max(fu,0,fu,1+λ,fu,2)

这样就把 u 的全部最优解统计了出来,答案即为 g1

则有转移方程:

fu,2=max{fu,2+gvfu,1+w(u,v)+fv,1fu,2}

第一行表示 u 不接到 v 上,直接继承 v 的最优解。

第二行表示把 u,v 两条未完成的链拼起来,得到一条完成的链。

fu,1=max{fu,1+gvfu,0+w(u,v)+fv,1fu,1}

第一行表示 u 不接到 v 上,直接继承 v 的最优解。

第二行表示 u 接到 v 上,继承 v 一条未完成的链,得到一条未完成的链

fu,0=max{fu,0+gvfu,0}

这里 u 必须不接 v ,只能取 v 的最优解。

时间复杂度 O(nlogV)

P6246 [IOI2000] 邮局 加强版 加强版

n 个村庄,需要放 m 个邮局,求每个村庄到最近邮局的距离和的最小值。

mn5×105

fi,j 表示前 i 个村庄放 j 个邮局的最小距离和,w(l,r) 表示在 [l,r] 范围村庄放一个邮局的最小距离和,则有:

fi,j=mink=0i1{fk,j1+w(k+1,i)}

决策单调性优化做到 O(n2)

考虑用 wqs 二分规避 j 的限制,于是得到一个1D/1D 的 DP,并且也有决策单调性,可以二分队列做到 O(nlognlogV)

P5308 [COCI 2018/2019 #4] Akvizna

你面临 n 名参赛者的挑战,最终要将他们全部战胜。

每轮可以选择淘汰一些选手,同时获得该轮淘汰人数除以该轮总人数的奖金。

需要举办 k 轮比赛使得最终只剩一个人,最大化奖金和。

n105

可以发现淘汰的顺序不影响答案,因此不妨每次将淘汰的人视为一段。

套路的,先用 wqs 二分规避 k 的限制。考虑倒序 DP,设 fi 表示从后往前数某轮还剩 i 个人的最大奖金,有:

fi=maxj<i(fj+iji)

假设对于 k<jj 优于 k ,则:

(1)fj+iji>fk+iki(2)fjfkjk>1i

直接斜率优化即可,时间复杂度 O(nlogV)

Slope Trick

Slope Trick 通常用于维护连续、分段、一次、凸函数,满足每段斜率较小且每段斜率为整数。

考虑维护某个点 x0 处的 f(x0)kx0 ,以及函数每个转折点(斜率突变的点)的集合。具体的,若函数在 x 处斜率增加了 Δk ,就在集合中插入 Δkx ,这样集合中相邻两个点的斜率差就为 1

事实上连续、分段、一次、凸函数的性质是很好的,可以支持很多操作,以下凸函数为例:

  • 相加:将 f(x0)kx0 直接相加,转折点集合直接合并即可。
  • 取前缀 min 或后缀 min :去掉 k>0k<0 的部分。
  • 求全局 min :仅保留 k=0 的部分。
  • 整体平移:维护 f(x0)kx0 的变化,转折点打全局平移标记。

P4597 序列 sequence

给定 a1n,每次可以将一个位置的数字加一或减一,求使得原序列不降的最少操作次数。

原题面还要求修改后的数列只能出现修改前的数,事实上归纳可以证明这个限制不会让答案变劣。

n5×105

fi,j 表示考虑前 i 个数,最后一个数为 j 的答案,则:

fi,j=|jai|+minkjfi1,k

Fi(j)=fi,j ,显然 FiFi1 取前缀 min 后加绝对值函数 y=|xai| 得到,答案即为 minFn(i)

考虑用堆维护 F ,记当前最右侧函数为 y=kx+b ,则:

  • 先取一遍前缀 min ,推平斜率 >0 的部分。
    • 对于转折点的维护,就直接弹出右边 k 个转折点即可。
    • 对于最右侧函数的维护,记当前要弹出的最右侧转折点为 x0 。由于 x0 同时满足左边和右边的一次函数,则 kx+b=(k1)x+b ,因此 b=b+x
  • 再加上一个绝对值函数 y=|xa|
    • 先合并转折点,直接往堆中加入两个 a 即可。
    • 再维护最右侧函数,新的最右侧函数为 y=(kx+b)+(xp)=(k+1)x+(bp)

时间复杂度 O(nlogn)

几道类似的题目:

[ABC217H] Snuketoon

有一个数轴上的游戏,0 时刻在 0 号节点。每时刻可以选择将坐标 ±1 ,或者不移动。

接下来按时间升序给出 n 个事件,每一个事件用 Ti,Di,Xi 描述。假设 Ti 时刻你在 p 点:

  • Di=0,则会受到 max{0,Xip} 的伤害。
  • Di=1,则会受到 max{0,pXi} 的伤害。

最小化 n 次事件所受伤害量。

n2×105

fi,j 表示 Ti 时刻在 j 可能的最小伤害,t 为与上一次的时间间隔,则:

fi,j=(mink=jtj+tfi1,k)+|jXi|[(j>Xi)=Di]

[l,r] 为斜率为 0 的段,可以发现一次更新就是把 <l 的部分和 >r 的部分向两边平移 t ,再加上一个只有半边的绝对值函数。

用一个大根堆和一个小根堆维护斜率为 0 的段两边的转折点,那么平移操作可以通过打标记实现。然后就是插入一个拐点 Xi ,根据 Xi 在斜率为 0 的段的左侧、右侧、中间,分类讨论贡献即可。

直接这么做会导致插入的拐点不在定义域范围内,一个做法是往两个堆中插入 n0 。由于扩大定义域的操作是平移操作,那么即使加入了定义域外的转折点,也不会从堆顶取出。

时间复杂度 O(nlogn)

CF1534G A New Beginning

在一个二维平面上,你一开始在 (0,0) ,只能向上或向右移动。

给定 n 个关键点点,第 i 个点为 (xi,yi) 。在点 (X,Y) 对点 (x,y) 打标记,需要花费 max(|Xx|,|Yy|) 的代价。

求标记所有点的最小代价。

n8×1050xi,yi109

首先套路地把切比雪夫距离转化为曼哈顿距离,于是问题转化为每次向右上或右下走一格,代价变为曼哈顿距离。

将所有点按 x 坐标排序,设 fi,j 表示标记到第 i 个点时 y 坐标为 j 的答案,则:

fi,j=|jyi|+mink=j(xixi1)j+(xixi1)fi1,k

直接开两个堆维护斜率为 0 的那段左右两边的转折点即可,时间复杂度 O(nlogn)

一道类似的题目:CF372C Watching Fireworks is Fun

P3642 [APIO2016] 烟火表演

给定一棵以 1 为根的 n+m 个节点的带边权树,其中叶子为 n+1n+m 。可以花费 |xy| 的代价将一条边的边权从 x 修改至 y ,最小化代价使得所有叶子到根节点的距离相同。

1n+m3×105

fu,i 为以 u 为根的子树中到叶子的距离为 i 的最小代价,有:

fu,i=vson(u)minji{fv,j+|w(u,v)(ij)|}

可以发现这是一个下凸函数,记 Fu(x)=minix{fu,i+|wx+i|}[l,r]fu 中斜率为 0 的段,则:

Fu(x)={fu,x+w(x<l)fu,l+wx+l(lx<l+w)fu,l(l+wxr+w)fu,r+xrw(x>r+w)

具体的:

  • x<l :因为改变边权的代价函数斜率为 1 ,而 f 函数 <l 的时候斜率一定 1 ,因此把边权改为 0 一定不劣。
  • lx<l+w :只要保证 x=l 就能取到函数的最小值,而 f 函数 <l 的时候斜率一定 1 ,因此尽量从 fu 的最小值转移一定不劣。
  • l+wxr+w :不用改变 w 就可以保证能取到最小值 fu,xw=fu,l
  • x>r+w :与第一条类似。

考虑一次更新对 F 的变化:

  • x<l :向上平移 w 单位。
  • lx<l+w :向上平移 w 后把斜率变为 1
  • l+wxr+w :将原先 [l,r] 的函数平移到 [l+w,r+w]
  • x>r+w :斜率变为 1

接下来考虑维护转折点集合,可以发现只要把 >l 的转折点全部删除,再加入 l+wr+w 两个转折点即可。

由于有求和操作,需要合并转折点集合,故考虑用可并堆维护转折点。

接下来考虑维护每个点的函数值,一个取巧的方法是发现 F1(0) 即为所有边权之和,因此最终可以将所有转折点拿出计算答案。

使用左偏树,时间复杂度 O((n+m)log(n+m)) ,注意左偏树要开两倍空间因为一个点会新增两个转折点。

CF280E Sequence Transformation

给定一个不降序列 x1n[1,V] 与两个整数 A,B

求一个实数序列 y1n[1,V] 满足 yiyi1[A,B] ,最小化代价 i=1n(xiyi)2

n6000

fi,j 表示前 i 个位置且 yi=j 的最小代价,则:

fi,j=(xij)2+mink=jBjAfi1,k

不难发现 Fi(j) 是一个凸函数,设 Fi1 的最小值点为 u ,则:

Fi(j)={Fi1(jA)+(xij)2(j<u+A)Fi1(u)+(xij)2(u+Aju+B)Fi1(jB)+(xij)2(j>u+B)

但是二次函数的斜率不是整数,并不好直接用 Slope Trick 维护。

发现凸函数求导后是单调函数,考虑对其求导:

Fi(j)={Fi1(jA)+2j2xi(j<u+A)2j2xi(u+Aju+B)Fi1(jB)+2j2xi(j>u+B)

发现其等价于把 u 左边的部分向右平移 A 单位, u 右边的部分向右平移 B 单位,然后中间部分变为 0 ,再给整体加上 2j2xi

观察上述转移,每次需要动态找到一个极值点。如果每次都暴力找,时间复杂度 O(n2) ,可以通过但不够优美。

由凸函数斜率单调的性质,考虑用平衡树维护所有斜率相同的段,每次找到跨过 0 点的段即可。然后,每次把左边的段打一个平移 A 的标记,右边的段打一个 B 标记,加入中间的 0 段,最后整体加一个一次函数就好了。

具体实现只要在 fhq-Treap 上维护平移量,和一个一次函数的标记即可,时间复杂度 O(nlogn)

闵可夫斯基和

定义:对于两个点集 A,B ,它们的闵可夫斯基和为点集 C={a+baA,bB}

考虑当 A,B 是凸包/凸壳的情况:

可以发现此时 C 也是凸包,并且 A,B 的边向量在 C 中恰好出现一次,即 C 的边就是把 AB 的边按斜率排序拼接而成的。

考虑 x{1,2,,n} 的两个下凸壳 f,g ,其差分数组分别单调。于是可以用 O(|f|+|g|) 的时间归并差分数组,得到 fg 的闵可夫斯基和。

考虑 (min,+) 卷积,记 hk=mini+j=kfi+gj 。由于 f,g 都是下凸壳,因此 h 实际上就是 fg 做闵可夫斯基和后的下凸包。因此采用闵可夫斯基和可以在线性时间内求出上/下凸包 (min,+) 卷积的结果。

[ABC383G] Bar Cover

给定权值 a1n 和常数 k ,一次操作可以覆盖一个 1×k 的区域。

对于 i=1nk ,求选 i 个长度为 k 的不交区间后选出区间内权值和的最大值。

n2×105kmin(n,5)

bi=j=ii+k1aj ,问题转化为在 b 中选若干个数,相邻两个数之间至少间隔 k1 个数,最大化所选数的和。

可以发现答案关于所选的数构成上凸壳。考虑分治,设 fi,j,t,gi,j,t 表示左/右区间选了 t 个数,其中左边空余至少 i 个,右边空余至少 j 个的最大和。转移就是对 fi,pgk1p,j(max,+) 卷积得到左右恰好空 i,j 个的答案,最后再更新一遍 f 即可。注意需要特殊转移左区间或右区间不选 b 的情况,直接做可以做到 O(nk3logn) ,难以通过。

注意到若区间长度不超过 k ,则区间最多只能选一个数,因此该部分区间无需分治,直接求即可。此时分治树上只有 nk 个叶子,而分治树的节点数与叶子数同阶,时间复杂度将为 O(nk2logn)

posted @   wshcl  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示