专栏文章

题解:AT_xmascon20_f Famous in Russia

AT_xmascon20_f题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miohuj3k
此快照首次捕获于
2025/12/02 19:27
3 个月前
此快照最后确认于
2025/12/02 19:27
3 个月前
查看原文

前言

题解字数较多,但作者认为还是相对浅显易懂的。

第一部分:这个题到底在干啥?

正如副标题所言,我们拿到这题,似乎无从下手。在此之前,我们不妨考虑这样一个更加简单的问题:
问题 1:
给定 a1an,b1bna_1\sim a_n,b_1\sim b_n,令 k=nk=n,求做菜吃菜最短时间。
解析:将菜品按照 bib_i 从大到小排序依次制作,答案为 maxi=1n(bi+j=1iaj)\max_{i=1}^n(b_i+\sum_{j=1}^ia_j)
证明:
利用调整法。对于一个不是按照 bib_i 从大到小排序的菜品序列,一定能找到下标 ii1i<n1\le i<n),使得 bi<bi+1b_i<b_{i+1}
j=1i1aj=x\sum_{j=1}^{i-1}a_j=x,那么 ii 处的答案为 ansi=x+ai+bians_i=x+a_i+b_ii+1i+1 处的答案为 ansi+1=x+ai+ai+1+bi+1ans_{i+1}=x+a_i+a_{i+1}+b_{i+1}
交换 i,i+1i,i+1 菜品,此时对于 i+2ni+2\sim n 以及 1i11\sim i-1 处,答案不变,而 i,i+1i,i+1 处的答案分别为 ansi=x+ai+1+bi+1,ansi+1=x+ai+ai+1+bians'_i=x+a_{i+1}+b_{i+1},ans'_{i+1}=x+a_i+a_{i+1}+b_i
  1. 由于 bi<bi+1b_i<b_{i+1},因此 ansi+1<ansi+1ans'_{i+1}<ans_{i+1}
  2. 由于 bi<bi+1b_i<b_{i+1},因此 bi<ai+1+bi+1b_i<a_{i+1}+b_{i+1},因此 x+ai+bi<x+ai+ai+1+bi+1x+a_i+b_i<x+a_i+a_{i+1}+b_{i+1},因此 ansi<ansi+1ans_i<ans_{i+1}
  3. 显然 x+ai+1+bi+1<x+ai+ai+1+bi+1x+a_{i+1}+b_{i+1}<x+a_i+a_{i+1}+b_{i+1},因此 ansi<ansi+1ans'_i<ans_{i+1}
  4. 因此,max(ansi,ansi+1)>max(ansi,ansi+1)\max(ans_i,ans_{i+1})>\max(ans'_i,ans'_{i+1}),交换显然更优。
对于上述问题,有没有一个更简单的刻画答案的方式?答案是肯定的。只需要将菜品按照 bib_i 从小到大排序,维护答案 ansans。遍历 i=1ni=1\sim n,令 ans:=max(ans,bi)+aians:=\max(ans,b_i)+a_i。这本质只是倒过来计算答案。
问题 2:
给定 a1an,b1bna_1\sim a_n,b_1\sim b_n,对于每个 kk,求做菜吃菜最短时间。
解析:首先,将菜品按照 bib_i 从小到大排序。忽略 aia_i 被钦定为 00 的菜品,在最后将答案与 bnb_n 取较大值即可。接下来,研究以下 dp:
dpi,j=min(dpi1,j,max(dpi1,j1,bi)+ai)dp_{i,j}=\min(dp_{i-1,j},\max(dp_{i-1,j-1},b_i)+a_i)
可以发现,dpi,jdp_{i,j} 表示在前 ii 个菜品中挑选 jj 个,仅它们的 aja_j 不被钦定为 00,此时的答案最小值。那么对于每个 kk,答案即为 ansk=max(dpn,k,bn)ans_k=\max(dp_{n,k},b_n)

第二部分:有点头绪了,我们来优化这个 dp 吧!

一个全新的问题出现在我们面前:咋优化这个 dp?我们需要利用一些结论。
结论 1:
dpi,jdpi,j+1,dpi,jdpi+1,jdp_{i,j}\le dp_{i,j+1},dp_{i,j}\ge dp_{i+1,j}
证明:
利用定义,可以发现在前 i+1i+1 个菜品中挑选 jj 个肯定不比在前 ii 个菜品中挑选劣,因为多了第 i+1i+1 个菜品供以选择。在前 ii 个菜品中挑选 jj 个肯定不比挑选 j+1j+1 个劣,因为多了一个需要选择的菜品。
根据结论 1 我们可以得知,对于每个 ii,我们可以找到唯一一个 jij_i1jii+11\le j_i\le i+1)使得对于所有 j<jij<j_idpi,jbidp_{i,j}\le b_i
结论 2:
jiji+1j_i\le j_{i+1}
证明:
根据结论 1,对于 j<jij<j_idpi+1,jdpi,jbibi+1dp_{i+1,j}\le dp_{i,j}\le b_i\le b_{i+1},因此 ji+1jij_{i+1}\ge j_i
结论 3(重要):
对于 j<jij<j_idpi,j=dpi1,jdp_{i,j}=dp_{i-1,j}
证明:
由于 dpi,j=min(dpi1,j,max(dpi1,j1,bi)+ai)dp_{i,j}=\min(dp_{i-1,j},\max(dp_{i-1,j-1},b_i)+a_i),而 max(dpi1,j1,bi)+ai>bi\max(dp_{i-1,j-1},b_i)+a_i>b_idpi,jbidp_{i,j}\le b_i,所以 dpi,j=dpi1,jdp_{i,j}=dp_{i-1,j}
结论 4(重要):
对于 j>jij>j_idpi,j=min(dpi1,j,dpi1,j1+ai)dp_{i,j}=\min(dp_{i-1,j},dp_{i-1,j-1}+a_i)
证明:
由于 dpi,j=min(dpi1,j,max(dpi1,j1,bi)+ai)dp_{i,j}=\min(dp_{i-1,j},\max(dp_{i-1,j-1},b_i)+a_i),而 dpi1,j1dpi,j1>bidp_{i-1,j-1}\ge dp_{i,j-1}>b_i,所以 dpi,j=min(dpi1,j,dpi1,j1+ai)dp_{i,j}=\min(dp_{i-1,j},dp_{i-1,j-1}+a_i)
铺天盖地的这么多结论,我们该如何利用它们呢?我们从差分数组考虑。
difi,j=dpi,jdpi,j1dif_{i,j}=dp_{i,j}-dp_{i,j-1}jijij_i\le j\le i)。
  • 对于 j=jij=j_i,由于 dpi,j1=dpi1,j1bidp_{i,j-1}=dp_{i-1,j-1}\le b_i,所以 dpi,j=min(dpi1,j,bi+ai)dp_{i,j}=\min(dp_{i-1,j},b_i+a_i)。如果 dpi1,jbi+aidp_{i-1,j}\le b_i+a_i,那么 difi,j=difi1,jdif_{i,j}=dif_{i-1,j},否则 difi,j=ai+bidpi,j1dif_{i,j}=a_i+b_i-dp_{i,j-1}
  • 对于 j>jij>j_i,利用结论 4,祭出下面这张图: .png 根据图可以发现,差分数组 difi,ji+1difi,idif_{i,j_i+1}\sim dif_{i,i} 本质上只是在差分数组 difi1,ji+1difi1,i1dif_{i-1,j_i+1}\sim dif_{i-1,i-1} 中插入了一个 aia_i,插入的位置 jj 满足 difi1,j>aidifi1,j1dif_{i-1,j}>a_i\ge dif_{i-1,j-1}
如上可得,对于 j>ji+1j>j_i+1difi,jdifi,j1dif_{i,j}\ge dif_{i,j-1}。而对于 j=jij=j_idifdif 的复杂讨论,可以总结为以下两点:
  • difi,jidif_{i,j_i} 对我们而言作用属实不大!我们更看重的是 dpi,jibidp_{i,j_i}-b_i 而非 dpi,jidpi,ji1dp_{i,j_i}-dp_{i,j_i-1}
  • 在这里,我们如果将 difi,jidif_{i,j_i} 的定义修改为 dpi,jibidp_{i,j_i}-b_i,我们就有能力扩展 j>jij>j_i 时的发现,甚至于将它与 j=jij=j_i 时的发现合并!
所以,我们修改差分数组 difdif 的定义。此时,记 difi,j=dpi,jdpi,j1dif_{i,j}=dp_{i,j}-dp_{i,j-1}ji<jij_i<j\le i),记 difi,ji=dpi,jibidif_{i,j_i}=dp_{i,j_i}-b_i
那么,difi,jdifi,j1dif_{i,j}\ge dif_{i,j-1}。差分数组 difi,jidifi,idif_{i,j_i}\sim dif_{i,i} 本质上只是:
  • 根据结论 3,在差分数组 difi1,ji1difi1,i1dif_{i-1,j_{i-1}}\sim dif_{i-1,i-1} 中切掉 difi1,ji1difi1,ji1dif_{i-1,j_{i-1}}\sim dif_{i-1,j_i-1} 不用。(步骤 1)
  • difi1,jidif_{i-1,j_i} 通过某种方式修改为 dpi,jibidp_{i,j_i}-b_i。(步骤 2)
  • difi1,jidifi1,i1dif_{i-1,j_i}\sim dif_{i-1,i-1} 中插入一个 aia_i,插入的位置 jj 满足 difi1,j>aidifi1,j1dif_{i-1,j}>a_i\ge dif_{i-1,j-1}。(步骤 3)
  • 得到 difi,jidifi,idif_{i,j_i}\sim dif_{i,i}
这样,我们就有能力利用小根堆维护差分数组 difdif
  • 每遇到一个 ii2in2\le i\le n),我们记 cur=bi1,id=ji1cur=b_{i-1},id=j_{i-1},然后依次弹出堆顶存储的元素 toptop
    • cur:=cur+topcur:=cur+top
    • 此时 cur=dpi,idcur=dp_{i,id}。根据结论 2,id<ji,cur=dpi,id=dpn,idid<j_i,cur=dp_{i,id}=dp_{n,id},我们显然可以在这里将 max(bn,cur)\max(b_n,cur) 贡献到 ansidans_{id} 当中。
    • id:=id+1id:=id+1
    直到 cur+top>bicur+top>b_i 为止(此时堆顶存储的是 toptop)。完成步骤 1。
  • 此时,ji=idj_i=id。我们想让这个堆中存储的东西变成 difi,iddifi,idif_{i,id}\sim dif_{i,i},具体地:
    • 堆中的 toptopdifi1,iddif_{i-1,id}。此时去除 toptop,插入 cur+topbicur+top-b_icur+topcur+topdpi,iddp_{i,id} 的值)。完成步骤 2。
    • 插入一个 aia_i。完成步骤 3。
初始时堆中只有一个 a1a_1

第三部分:道理我都懂了,但是我们不知道 aia_i,该咋办?

我们总结一下。
通过前两部分,我们得到了一个基于小根堆的一个算法,快速求解 dp 值贡献到答案中。但由于我们不知道 aia_i 的值,这个算法似乎没什么实际用途。除非,我们把这个小根堆本身压入一个新的 dp,形成 dp 套 dp。
略微修改一下上述算法,将 idid 变为全局变量便于操作,得到以下算法:
  • 初始时堆中只有一个 a1a_1id=1id=1
  • 每遇到一个 ii2in2\le i\le n),记 cur=bi1cur=b_{i-1},依次弹出堆顶存储的元素 toptop
    • cur:=cur+topcur:=cur+top
    • max(bn,cur)\max(b_n,cur) 贡献到 ansidans_{id} 当中。
    • id:=id+1id:=id+1
    直到 cur+top>bicur+top>b_i 为止。
  • 去除 toptop,插入 cur+topbicur+top-b_i
  • 插入一个 aia_i(根据先前插入 aia_i 的规定,插入相同数值的元素将会被认为按照插入顺序从前到后排列)。前往 i+1i+1 循环上述操作。
那我们的任务就是,将这个小根堆压入新的 dp 状态中。对于一个小根堆中的一个元素 xx,我们需要知道:
  • xx 的值。
  • ii 的值,为了得知 bi1b_{i-1} 的值。
  • 处在 xx 前面的所有元素(包括 xx 本身)的数量 jj,为了得知答案贡献到 ansans 的哪个下标(id=jid=j)。
  • 处在 xx 前面的所有元素(包括 xx 本身)的和 sumsum,为了结合 ii 的值得知 curcur 的值。
gi,j,sum,xg_{i,j,sum,x} 表示小根堆满足下标所示条件的 a1ai1a_1\sim a_{i-1} 的组数。对于 ai[1,v]a_i\in[1,v],我们尝试追踪 xx 的去向:
  • 首先,如果 sum+bi1bisum+b_{i-1}\le b_i,这意味着 xx 这个元素将会在这一轮被弹出,将 max(bn,sum+bi1)×gi,j,sum,x×vni+1\max(b_n,sum+b_{i-1})\times g_{i,j,sum,x}\times v^{n-i+1} 贡献到 ansjans_j 中,不做任何转移。其中 vni+1v^{n-i+1} 代表着 aiana_i\sim a_n 的值任意。
  • 如果 sum+bi1>bisum+b_{i-1}>b_i,这意味着 xx 将会在这一轮被保留。记 w=min(x,sum+bi1bi)w=\min(x,sum+b_{i-1}-b_i)ww 将会是 xx 在这一轮之后的值。枚举 aia_i
    • 如果 ai<wa_i<w,那么 gi+1,j+1,sum+bi1bi+ai,wgi,j,sum,xg_{i+1,j+1,sum+b_{i-1}-b_i+a_i,w}\larr g_{i,j,sum,x}
    • 如果 aiwa_i\ge w,那么 gi+1,j,sum+bi1bi,wgi,j,sum,xg_{i+1,j,sum+b_{i-1}-b_i,w}\larr g_{i,j,sum,x}
    • 在这里,根据插入 aia_i 的规定,我们需要时刻记住,小根堆中的值是按大小为第一关键字,插入顺序为第二关键字排序的。因此 ai=wa_i=w 时将会归类到 ai>wa_i>w 的情况中。
据此,我们解决了几乎整道题目。上述 dp 几乎完美,只有一个问题:列出的转移式只是针对 a1ai1a_1\sim a_{i-1} 这种以前已经被插入进来的元素进行实时追踪,插入的 aia_i 该如何统计到 gg 中并随着转移在以后追踪呢?

第四部分:解决新加入的 aia_i 无法统计的问题

绞尽脑汁,我们似乎没有办法解决这个问题。我们的状态定义还是太简单了,似乎无法支持我们定位插入的 aia_i 的位置。不妨更改状态,我们额外记一个信息:
  • 处在 xx 后面的最靠前的元素(不包括 xx)的值 nxtnxt
根据插入 aia_i 的规定,我们需要时刻记住,小根堆中的值是按大小为第一关键字,插入顺序为第二关键字排序的。这样,我们得知假如 aia_i 被插入到 xxnxtnxt 之间,那么它一定满足 xai<nxtx\le a_i<nxt
对于每个 xx,在 xx 处定位所有满足 xai<nxtx\le a_i<nxtaia_i。具体地,记 fi,j,sum,x,nxtf_{i,j,sum,x,nxt} 表示小根堆满足下标所示条件的 a1ai1a_1\sim a_{i-1} 的组数。接下来定位 xx 的去向以及追踪 aia_i
  • 如果 sum+bi1bisum+b_{i-1}\le b_i,则将 max(bn,sum+bi1)×fi,j,sum,x,nxt×vni+1\max(b_n,sum+b_{i-1})\times f_{i,j,sum,x,nxt}\times v^{n-i+1} 贡献到 ansjans_j 中,不做任何转移。
  • 如果 sum+bi1>bisum+b_{i-1}>b_i,记 w=min(x,sum+bi1bi)w=\min(x,sum+b_{i-1}-b_i)。枚举 aia_i
    • 如果 ai<wa_i<w,那么 fi+1,j+1,sum+bi1bi+ai,w,nxtfi,j,sum,x,nxtf_{i+1,j+1,sum+b_{i-1}-b_i+a_i,w,nxt}\larr f_{i,j,sum,x,nxt}
    • 如果 aiwa_i\ge w,那么 fi+1,j,sum+bi1bi,w,min(ai,nxt)fi,j,sum,x,nxtf_{i+1,j,sum+b_{i-1}-b_i,w,\min(a_i,nxt)}\larr f_{i,j,sum,x,nxt}
  • 追踪满足 xai<nxtx\le a_i<nxtaia_i,也就是令 fi+1,j+1,sum+bi1bi+ai,ai,nxtfi,j,sum,x,nxtf_{i+1,j+1,sum+b_{i-1}-b_i+a_i,a_i,nxt}\larr f_{i,j,sum,x,nxt}。这使得我们的视角转换到 aia_i 上。
到此为止,问题基本完成,剩下的便是一些小角箱子(corner case),例如小根堆中不存在元素该怎么办,nxtnxt 不存在该怎么办,以及 aia_i 若插入到小根堆堆头则上述转移无法统计到它等问题。这一部分留给读者自行推导,以加深理解。

总结

这个做法的时间复杂度为 O(n3v4)O(n^3v^4),空间复杂度经滚动数组可以优化到 O(n2v3)O(n^2v^3)

评论

0 条评论,欢迎与作者交流。

正在加载评论...