Educational Codeforces Round 96 (Rated for Div. 2)/Codeforces1430 题解ABCDEF

AC代码

A. Number of Apartments

这题其实直接暴力就可以了,我还想了挺久想出了另外一个解法。

初始时,3,5,7是可行的,然后(n)可以从(n-3)(n-5)或者(n - 7)处转移得到。

(O(n))预处理,(O(1))回答询问。

B. Barrels

降序排序,将第(2)(k + 1)范围内所有的水都倒到(1)处。此时,(a_1)为最大值,(0)为最小值,故(a_1)即为答案。

C. Numbers on Whiteboard

通过观察易得:最后剩下的数字大于等于2。

先合并(a_{n-2})(a_n),将结果放到数组末尾。

然后不断合并数组的末尾两项,将结果放到末尾。

这样操作,最后剩下的数字必定为2。

D. String Deletion

将连续且相同的元素视为一个段。

  • 如果只有一个段,那么直接删掉这个段。
  • 如果第一个段的长度大于等于2,那么可以删除其中一个,再将该段删除。
  • 如果第一个段的长度等于1
    • 如果后面有长度大于等于2的段,就从后面删一个(段长度减一),然后将第一个段删除。
    • 否则,把最后一个段删掉,然后将第一个段删掉。

E. String Reversal

从末尾开始,每次满足一个位置的限制条件。假设翻转后的串为(t_i),那么就依次满足(t_n)(t_{n-1}),...,(t_1)

在满足(t_i)时,贪心的使用离它最近且和它相等的字符。记(st)是最大的且满足(s_j = t_i)(j),然后从(st)开始,将其不断和下一位交换,直到(st = i),耗费(i - st)步。

现在就只需要快速的计算(st)了。首先对于每一个字母,用一个数组记录这个字母在原串中的位置,数组内元素升序。这样,每次满足(t_i)时,使用的元素必定是对应数组的末尾。

现在还有一个问题就是,数组记录的是初始位置,在多次操作后,元素目前的位置可能会前移。为了解决这个问题,就用一个树状数组记录初始位置位于(i)的元素是否已经被使用。记当前要使用的元素初始位置为(from),那么元素当前位置(st = from - f(from - 1)),其中(f(i))表示([1, i])中已经被使用的元素个数。

F. Realistic Gameplay

根据观察:对于一波怪物,最优的操作是在开始的瞬间打光弹夹中的子弹,然后开始装弹,但后再瞬间打光,不断重复。

(dp_i)表示从第(i)波怪物开始到第(n)波怪物,要想在规定时间内杀完所有怪物,(l_i)时弹夹中最少需要多少子弹,也即(l_i)时至少需要消灭多少怪物。

记第(i)波需要消灭(need)只怪,也即([l_i, r_i])这段时间内需要消灭(need)只怪。则(dp_i = max(0, need - k * (r_i - l_i)))。其中(need = a_i + dp_{i + 1}[r_i = l_{i+1}])。特别地,如果初始时满弹夹并用最优操作也打不完怪,则无解。

逆序跑dp,就可以求出所有的(dp_i)

现在开始正序打怪,假设弹夹中剩余子弹数量为(remain)。那么从头到尾遍历一遍(dp_i),如果(remain < dp_i),则必须要换弹才能打完所有怪,这个时候需要丢弃(remain)颗子弹。然后消灭(a_i)个怪,消耗(a_i)颗子弹,然后更新remain。

丢弃和打怪消耗的子弹数量和即为答案。

原文地址:https://www.cnblogs.com/zengzk/p/13798917.html