Educational Codeforces Round 96 (Rated for Div. 2)/Codeforces1430 题解ABCDEF
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。
丢弃和打怪消耗的子弹数量和即为答案。