2022“杭电杯”中国大学生算法设计超级联赛(3)

A. Equipment Upgrade

Ei表示从等级i强化至等级n的期望花费,则有
En=0Ei=ci+piEi+1+(1pi)j=1iwj(j=1iwjEij)piEi+1=Eici(1pi)j=1iwj(j=1iwjEij)Ei+1=Eici(1pi)j=1iwj(j=1iwjEij)pi

根据上式,如果已知E0,E1,,Ei,即可计算出Ei+1的值。但是由于E0未知,我们无法从前往后进行递推。在这里,设Ei=aiE0+bi,则
a0=1b0=0ai+1=ai(1pi)j=1iwj(j=1iwjaij)pibi+1=bici(1pi)j=1iwj(j=1iwjbij)pi

此时ab都是可以从前往后递推计算的,且计算过程是卷积的形式,可以用分治+NTT求出,最后根据anE0+bn=En=0解出E0的值即为答案。

时间复杂度O(nlog2n)

  

B. Boss Rush

二分答案,转化为判断T帧内能否打败BOSS,即求出T帧内能打出的最高伤害,判断是否大于等于H

从前往后依次发动若干个技能,则下一个技能可以发动的时刻等于之前发动过的技能的演出时间之和,因此只和之前发动过哪些技能有关。设fS表示发动了S 集合的技能,在T帧内最多能结算多少伤害,枚举不在S中的某个技能x作为下一个技能进行转移,由于技能发动时刻已知,因此可以O(1)计算出在T帧内下一个技能可以结算多少伤害。

时间复杂度O(n2nlogans)

  

C. Cyber Language

签到模拟,遍历每个字符,如果一个字符是小写字母且前一个字符是空格或者它是第一个字符,那么把它转大写输出。

  

D. Divide the Sweets

sumS表示S集合的箱子的糖果数之和,fi,S表示把S集合的箱子分给i个孩子的最小平方和,则fi,S=min(fi1,T+(sumSsumT)2),其中TS的子集。直接枚举子集转移的时间复杂度为O(m3n),不能接受。

方便起见,令gS=fi,S,hS=fi1,S,则

gS=min(hT+(sumSsumT)2)=min(hT+sumS2+sumT22sumSsumT)=min((hT+sumT2)2sumSsumT)+sumS2

将表示集合的n位二进制数拆成前n2位和后n2位来考虑。枚举转移中T的前n2A,再枚举A的所有超集A作为S的前半部分,然后枚举S的后n2B,此时S=AB,我们需要找到一个B的子集B作为T的后半部分(即T=AB),满足(hT+sumT2)2sumSsumT最小。这是经典斜率优化的形式,对于每个T,将其看作直线y=sumTx+(hT+sumT2),若能得到B子集的所有直线形成的凸壳,则在凸壳上询问x=2sumSy的最小值即可完成状态转移。假设已经有了凸壳,为了保证询问的均摊复杂度为O(1),需要按照sumS递增(或递减)的顺序去询问,由于sumS=sumA+sumB,所有的S对应的B都相等,因此按照sumA递增(或递减)的顺序去枚举A即可保证询问x坐标的单调性。

剩下的问题是如何得到B子集的凸壳。类似于高维前缀和,对于每个状态B保存其凸壳。一开始对于每个状态B,它的凸壳大小为1,对应T=AB。接下来依次枚举后半部分的每一位,假设当前枚举到了第x位,对于一个集合B,如果它的第x位为1,则它缺少 B xor (1<<x) 的信息,暴力将 B xor (1<<x) 和B的凸壳二路归并成一个,作为B的新凸壳。最坏情况下,每次合并后凸壳大小翻倍,总代价为最终凸壳大小的两倍,所有状态的凸壳大小不超过子集数,因此预处理子集凸壳的时间复杂度为O(3n2)

总时间复杂度分析:一共要进行O(m)轮,每轮需要枚举O(2n2)A,然后枚举它的超集A,总计O(3n2),每个A又需要接着枚举O(2n2)个后半部分B,然后花费均摊O(1)的代价在子集的凸壳上进行询问,这部分每轮的总时间复杂度为O(3n22n2)=O(6n2)。而枚举完A后,又需要支付O(3n2)的代价预处理出所有子集的凸壳,这部分每轮的总时间复杂度也为O(6n2)。因此,最终得到总时间复杂度为O(m6n2)

  

E. Spanning Tree Game

题意即对于每个k (0km),从数组a中选取k个边权,从数组b中选取mk个边权,并最大化最小生成树的边权和。

对于一条边(u,v,a,b),有以下两种情况:

  • a<b:拆成两条边(u,v,a,1)(u,v,b,0)
  • ab:拆成两条边(u,v,b,1)(u,v,a,0)

根据最小生成树的Kruskal算法,将拆后的2m条边按边权从小到大排序,边权相同时,将类型(101)为0的边排在后面,从前往后依次考虑每条边:

  • 若是(u,v,w,1),则这条边可选可不选,若选了则a数组中选取的边数要增加1,此时若uv不连通,则MST的边权和要增加w
  • 若是(u,v,w,1),则这条边可选可不选,若选了则a数组中选取的边数要减少1,此时若uv不连通,则MST的边权和要增加w
  • 若是(u,v,w,0),则这条边对应的另一条边在此之前已经考虑过。若另一条边选了,则这条边选上不会对MST产生多余的错误贡献;若另一条边没选,则这条边必须要选。因此,此时如果判断出uv不连通,则MST的边权和要增加w

上述过程中每条边可能会有两种选择,使得整个图中n个点的连通情况不同,由此设计出状态fi,S,j表示考虑了排序后前i条边,n个点连通性的最小表示为S,有j条边边权来自数组a时,最小生成树边权和的最大值是多少。预处理转移后可以做到O(1)转移。

状态数分析:ij都是O(m)个,SBell(n)个,其中Bell(9)=21147

时间复杂度O(m2Bell(n))

  

F. Dusk Moon

对于一个点集,它的凸包覆盖住了所有点,且最小覆盖圆覆盖住了凸包,因此仅保留凸包的顶点不会影响答案。

由于点的坐标在给定的正方形范围内随机,因此一个点集的凸包的期望顶点数为O(logn),使用线段树直接记录区间凸包点集,然后对于O(logn)个点运行最小圆覆盖算法即可。

时间复杂度O(qlog2n)

  

G. Shallow Moon

w行为一块,将m×m的矩阵从上到下分为mww×m的块。其中最后一块可能不足w行,方便起见下面都忽略这种情况。

由于每块的行数和每个矩形障碍的行数相等,因此每个矩形障碍要么完全属于某一块,要么经过相邻的两块。一个矩形障碍对于某一块的影响只能是下列两种情况之一:

  • 块内第b列至第b+h1列的前若干行是障碍。
  • 块内第b列至第b+h1列的后若干行是障碍。

对于某块中固定的某一列,只需要考虑上述第一种情况中下边界最靠下的限制,以及第二种情况中上边界最靠上的限制,那么这一列要么都是障碍,要么能走的行数是一个连续的区间。假设某一块中有k个矩形障碍,那么按照每个障碍的左右边界将这一块w×m的区域从左往右离散成O(k)个行数为w的区域,每个区域中最多只有一个连续的行区间可以行走。由于所有障碍的列数都为h,可以通过单调队列在O(k)时间内求出每个区域的可走区间。至此,我们成功地将一个包含k个矩形障碍的块的可走区域从左往右划分成了O(k)个矩形。

由于每块至少贡献一个区域,而总障碍数为O(n),因此上述方法会得到O(n+mw)个矩形区域,当mw较大时会退化,这是因为很多块一个障碍都没有,此时需要把连续的不含障碍的块合并成一个,则最终我们得到了O(n)个矩形区域。

对这O(n)个矩形区域建图,每个点代表一个区域,点权为区域的面积,若两个区域相邻则连边,答案即为每个连通块的点权和的平方之和。在这里,连边有以下两种情况:

  • 同一块内左右相邻的两个区域需要连边,边数显然为O(n)
  • 相邻两块内上下相邻的两个区域需要连边,可以通过双指针实现,边数为相邻两块区域数之和,总边数仍为O(n)

时间复杂度O(nlogn),使用基数排序可以做到O(n)

  

H. Laser Alarm

三个不共线的点可以确定一个平面。对于任意一个平面,将其调整至经过三个顶点,结果不会变差。因此枚举三个顶点得到平面,然后O(n)计算触碰了该平面的线段数,更新答案即可。所有点都共线的情况需要特判。

时间复杂度O(n4)

  

I. Package Delivery

考虑r最小的那个区间k,第一次取快递放在第rk天一定不会使结果变差。此时可能有很多区间覆盖了rk,那么为了尽量延后下一次取快递的日期,此时的最优策略应该是选择覆盖rkr值最小的k个区间,使用堆找到并去掉这些区间后,问题就递归了。重复上述过程直至处理完所有n个区间。

时间复杂度O(nlogn)

  

J. Range Reachability Query

离线询问,设fi,j表示i点能否仅通过编号在[lj,rj]之间的边走到第j个询问的目的地vj,共O(nq)个01状态,可以使用bitset存储。第j个询问的答案即为fuj,j

考虑一条边uv的转移,假设它的编号为k,令所有满足lkr的询问的集合为S,则有f[u] |= f[v] & S。接下来考虑如何得到集合S,一个直接的想法是从1m依次考虑每条边,维护覆盖当前边的询问集合,每个询问拆成两个事件:

  • l处加入集合。
  • r+1处离开集合。

上述方法需要保存m个bitset,空间复杂度过高。节省空间的方法是每O(q)个事件保存一次bitset,这样只需保存O(q)个bitset,然后每次要得到集合S时,再往对应bitset的副本中暴力模拟O(q)个事件。

总时间复杂度O(mqw+mq)

  

K. Taxi

如果没有w的限制,那么是经典问题。根据|x|=max(x,x),有

max{|xxi|+|yyi|}=max{max(xxi,x+xi)+max(yyi,y+yi)}=max{xxi+yyi,x+xi+yyi,xxiy+yi,x+xiy+yi)}=max{(x+y)+(xiyi),(xy)+(xi+yi),(x+y)+(xiyi),(xy)+(xi+yi)}

分别记录xi+yixiyixi+yixiyi的最大值即可在O(1)时间内求出所有点到(x,y)的曼哈顿距离的最大值。

现在考虑加入w的限制。将所有城镇按照w从小到大排序,并记录排序后每个后缀的xi+yixiyixi+yixiyi的最大值,用于O(1)求给定点(x,y)到该后缀中所有点的距离最大值。

选取按w排序后的第k个城镇,O(1)求出给定点(x,y)到第k..n个城镇的距离最大值d,有两种情况:

  • wk<d,那么第k..n个城镇对答案的贡献至少为wk。用wk更新答案后,由于第1..k个城镇的w值均不超过wk,因此它们不可能接着更新答案,考虑范围缩小至[k+1,n]
  • wkd,那么第k..n个城镇对答案的贡献为d。用d更新答案后,考虑范围缩小至[1,k1]

容易发现每次考虑的范围都是一个区间,如果每次取k为区间的中点,那么迭代O(logn)次即可得到最优解。

时间复杂度O((n+q)logn)

  

L. Two Permutations

首先特判序列S中每个数字出现次数不都为2的情况,此时答案为0

动态规划,设fi,j表示P的前i项匹配上了S,且Pi匹配S中数字Pij次出现的位置时,有多少种合法的方案。由于S中每个数字出现次数都为2,因此状态数为O(n)。转移时枚举Pi+1匹配哪个位置,那么Pi匹配的位置与Pi+1匹配的位置中间的那段连续子串需要完全匹配Q中对应的子串,使用字符串Hash进行O(1)判断即可。

时间复杂度O(n)

  

posted @   Claris  阅读(385)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
历史上的今天:
2017-07-26 BZOJ4167 : 永远的竹笋采摘
2015-07-26 BZOJ3456 : 城市规划
点击右上角即可分享
微信分享提示