zoukankan      html  css  js  c++  java
  • 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。

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

  • 相关阅读:
    poj 3264(RMQ或者线段树)
    LCA上的RMQ模板算法
    LCA离线算法Tarjan的模板
    poj 1330(初探LCA)
    hdu 3367(与最大生成树无关。无关。无关。重要的事情说三遍+kruskal变形)
    hdu 4496(并查集逆向添边)
    hdu 1829(继续扩展并查集)
    poj 1182 (扩展并查集)
    hdu 3038(扩展并查集)
    hdu 3371(kruskal)
  • 原文地址:https://www.cnblogs.com/zengzk/p/13798917.html
Copyright © 2011-2022 走看看