【题解】牛客练习赛91
   前言:   
     本次比赛题目比较偏向思维,所用到的算法知识点不会太深。  
     接下来背下锅,很抱歉有人反映C题被卡常。因为std没有任何优化大概500+MS,内测时大家貌似也没有出现被卡常的现象,所以就觉得应该1s足够。没想到比赛期间因为测评机波动,加上可能确实有些算法常数过高,导致了卡常发生,真是抱歉QAQ。  
     A-神奇天平   
 考点:数学对于当前
①若
②若
重复以上过程,最终便可找到重的那件物品,不难发现这个过程本质上就是求
以上是正常的思考过程,实际上打个表找找规律应该就能通过此题(跑
   时间复杂度:)) 。
。  
     B-魔法学院(easy version)   
      考点:差分、贪心   
       对于某个字符 ,我们可以用差分或者贪心的方法处理出他们在
,我们可以用差分或者贪心的方法处理出他们在 上的覆盖区间。然后接着从
上的覆盖区间。然后接着从 枚举到
枚举到 ,若下标
,若下标 处的字符可以修改为
处的字符可以修改为 ,则令
,则令) 即可。枚举完
即可。枚举完 种字符后,再对字符串
种字符后,再对字符串 统计价值和便可得到最终答案。
统计价值和便可得到最终答案。   
       时间复杂度:) 。
。   
       C-魔法学院(hard version)    
        考点:并查集、双向链表    
         我们不妨从高价值字符枚举到低价值字符,那么对于高价值字符覆盖过的区间,低价值字符就没有必要去遍历了。因此遍历时,我们使用并查集或者双向链表对之前覆盖过的区间进行跳跃即可,具体可见代码。    
         时间复杂度:) 。
。    
         D-监狱逃亡     
       考点:树状数组、线段树   
       首先预处理出每行的前缀和数组,接着注意到行数只有三,于是我们用 表示从第一行下到第二行的下标,用
表示从第一行下到第二行的下标,用 表示从第二行下到第三行的下标,那么问题可以转化成,求满足
表示从第二行下到第三行的下标,那么问题可以转化成,求满足) 的
的) 对数。
对数。   
       我们对上式移项,变为) 。显然可以类比逆序对,对其离散化后利用树状数组或者线段树进行求解。
。显然可以类比逆序对,对其离散化后利用树状数组或者线段树进行求解。   
       时间复杂度:)) 。
。   
       E-游戏人生    
       考点:二分、优先队列   
        显然玩家的初始生命值越多,通关的可能性就越大,因此我们对答案进行二分,那么题目转化成给定玩家初始生命值,判断玩家是否能通关。这个可以使用反悔贪心的方法来实现,具体如下:    
         ①使用两个变量 与
与 记录到当前回合,使用了多少次普通攻击和狂暴攻击。
记录到当前回合,使用了多少次普通攻击和狂暴攻击。    
         ②使用一个大根堆保存到当前回合,反悔后玩家能回复的生命值。    
         ③每个回合开始时,首先我们默认使用狂暴攻击,对boss造成 点伤害,玩家生命值减
点伤害,玩家生命值减 ,并令
,并令 。
。    
         ④若玩家的生命值小于等于 了,我们进行反悔操作:
了,我们进行反悔操作:    
         1. 如果 和
和 都为
都为 ,表示已经无法通过反悔来回复生命值了,因此无法通关。
,表示已经无法通过反悔来回复生命值了,因此无法通关。    
         2. 如果 为
为 ,
, 不为
不为 ,则只能通过将某次狂暴攻击反悔为普通攻击来回复生命值,因此玩家的生命值加
,则只能通过将某次狂暴攻击反悔为普通攻击来回复生命值,因此玩家的生命值加 ,boss的生命值加
,boss的生命值加 ,并令
,并令 ,
, 。
。    
         3. 如果 不为
不为 ,
, 为
为 ,则只能通过将某次普通攻击反悔为防御来回复生命值,因此玩家的生命值加堆顶元素,boss的生命值加
,则只能通过将某次普通攻击反悔为防御来回复生命值,因此玩家的生命值加堆顶元素,boss的生命值加 ,弹出堆顶,并令
,弹出堆顶,并令 。
。    
         4. 如果 和
和 都不为
都不为 ,则判断
,则判断 与堆顶元素的大小,选择回血量更大的操作进行反悔。
与堆顶元素的大小,选择回血量更大的操作进行反悔。    
         ⑤接着判断boss生命值是否小于等于 ,如果是表示能够通关。
,如果是表示能够通关。    
         ⑥然后boss攻击,玩家生命值减少 ,并将这次反悔后能回复的生命值压入堆。
,并将这次反悔后能回复的生命值压入堆。    
         ⑦若玩家的生命值小于等于 了,我们进行反悔,具体操作同④。
了,我们进行反悔,具体操作同④。    
         从内测来看,本题还有线段树的单log做法。    
         时间复杂度:%20%5Ctimes%20log(n))) 。
。    
         F-卡牌大师     
         考点:思维    
         设 的长度是
的长度是 ,考虑每个长度为
,考虑每个长度为 的后缀
的后缀 到
到 ,某个
,某个 想和某个
想和某个 相加得到
相加得到 或者
或者 ,那一个
,那一个 只有一个对应的
只有一个对应的 ,所以每个关系,只取一边即可。具体的,
,所以每个关系,只取一边即可。具体的, 对应
对应 ,
, 对应
对应 ,中点讨论一下,然后算一下
,中点讨论一下,然后算一下 到
到 分布在四个块里面的数量,每个互斥的块取其中之一。
分布在四个块里面的数量,每个互斥的块取其中之一。    
       时间复杂度:)) 。
。   
     G-区间加    
       考点:线段树   
       不算难的数据结构题,主要难度可能在于编程。   
       考虑某一个普通的数 生命历程的所有状态:原数→一直加
生命历程的所有状态:原数→一直加 变成只有
变成只有 个
个 →再一直加
→再一直加 直到和
直到和 合并→只有
合并→只有 个
个 。对于第二个过程,一个数只会最多加
。对于第二个过程,一个数只会最多加 次,对于第三个过程,每个数最多只会合并一次,第四个过程之后就相当于每次给这个数乘
次,对于第三个过程,每个数最多只会合并一次,第四个过程之后就相当于每次给这个数乘 了。
了。
   
       因此,我们对每个数 ,如果
,如果 ,那么我们另外开一棵线段树维护,在这棵线段树上
,那么我们另外开一棵线段树维护,在这棵线段树上 ,
, 操作都相当于区间乘
操作都相当于区间乘 ;否则我们把
;否则我们把 最高位和其它位分开,记为
最高位和其它位分开,记为 和
和 。
。
   
       对于加 操作:等价于给区间的
操作:等价于给区间的 乘
乘 。
。   
       对于加 操作:如果区间
操作:如果区间 存在
存在 ,我们暴力找到这个
,我们暴力找到这个 ,给它加上
,给它加上 ,直到
,直到 ;否则,操作等价于给区间的
;否则,操作等价于给区间的 乘
乘 。
。
   
       接下来只剩一个问题,就是要把 的数合并,并插入到
的数合并,并插入到 的线段树中。对于这个问题,我们可以维护区间
的线段树中。对于这个问题,我们可以维护区间 的差的最小值
的差的最小值 ,每次加
,每次加 ,相当于给区间的
 ,相当于给区间的 加
加 ,加
,加 相当于给区间的
相当于给区间的 减
减 。如果区间存在一个
。如果区间存在一个 ,我们就暴力找到这个位置,把
,我们就暴力找到这个位置,把 和
和 合并,插入到另—棵线段树中,并把
合并,插入到另—棵线段树中,并把 赋值为
赋值为 。
。
    
        每次询问就是把区间的 ,
,  ,
, 加起来。
加起来。
考虑时间复杂度,对于加 操作,每个数只会加
操作,每个数只会加 次,每次需要
次,每次需要) 访问到这个数,这部分总复杂度是
访问到这个数,这部分总复杂度是) ;对于合并
;对于合并 和
 和 的操作,每个数只会合并一次,需要
的操作,每个数只会合并一次,需要) 访问到这个数,这部分总复杂度是
访问到这个数,这部分总复杂度是) ;其它部分总时间复杂度均为
;其它部分总时间复杂度均为) 。因此这题时间复杂度是
。因此这题时间复杂度是%20%5Ctimes%20log(V))) 。
。    
    考虑时间复杂度,对于加
     时间复杂度:%20%5Ctimes%20log(V))) 。
。    
        代码:     
                               
 网易游戏公司福利 555人发布
网易游戏公司福利 555人发布