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。

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

posted @ 2020-10-11 19:45  _Backl1ght  阅读(284)  评论(0编辑  收藏  举报