Codeforces Round #668 (Div. 2)/Codeforces1405 题解(A-E)
A. Permutation Forgery
逆序输出排列\(p\)即可。
B. Array Cancellation
依据题意,若\(a_i\)大于\(0\),那么\(a_i\)可以免费地用在增加后续值为负的元素。
从前往后遍历数组\(a\),用一个计数器记录可免费用的正数和,每遇到一个正的\(a_i\)就加到计数器上;遇到负的\(a_i\)时就尽可能地用花费免费可用的正数去增加这个\(a_i\)。
这样遍历完一遍之后,数组中的元素就都只能花钱去操作了,求正元素的和或者求负元素的和后取相反数都可以。
C. Balanced Bitstring
通过观察可以发现:满足条件的01串必定以\(k\)为周期。
然后就只需要判断\(s\)是否可能以\(k\)为周期,以及\(s[0...k-1]\)是否可能满足条件。
D. Tree Tag
实际上就是若Alice和Bob之间的距离小于等于\(da\),那么Alice就赢了。
感觉sample2就是在暗示讨论一条链,在最好的情况下也就是树的直径就可以。
首先,Bob最优的操作就是先躲到直径的一端,然后等者Alice靠近时再借机跳走。
然后,在最差的情况下,Alice和Bob之间的距离为\(da+1\),也就是若Alice再靠近Bob一步且Bob不操作,Bob就输了。这个时候,若Alice不靠近,Bob就不需要操作;若Alice靠近,Bob就需要跳到离Alice新位置的距离大于\(da\)的位置。Alice用最优操作的情况下,Bob的移动距离要大于\(2da+1\)。
然后就可以得出结论:当且仅当Alice和Bob的初始距离大于\(da\),且\(db\)和树的直径都大于等于\(2da + 1\)时,Bob胜,反之Alice胜。
E. Fixed Point Removal
首先,用\(i-a_i\)替换\(a_i\),这样,题目中允许的操作就变为删除一个零,然后将后面的所有元素都减一。
然后,先读进来所有的询问,然后离线地回答询问。
记\(f(l, r)\)为仅考虑子数组\(a[l...r]\)时,最多能删除多少个元素。
通过观察可以得到:若\(i < j\),则\(f(i,r) \ge f(j, r)\)。因为对于\(a[i...r]\)而言,最差也就是只使用\(a[j...r]\)的元素,所以对于固定的\(r\),\(f(i,r)\)随着\(i\)的增加不减。
从小到大枚举右端点\(r\),现在\(r\)就可以视为常数。用一个数组\(s\)记录右端点为\(r\)时,各个左端点的答案,即\(s_i = f(i, r)\)。
若\(a_r < 0\),那么无论怎样这个元素都无法被删除;反之,对于任意一个左端点\(l\),如果\(f(l,r) \ge a_r\),那么对于这个区间而言,就可以先删除\(a_r\)个元素,然后再删除\(a_r\),再执行剩下的操作,即删除\(a_r\)并不会影响前面的操作。所以,若\(f(l,r) \ge a_r\),则\(f(l,r)=f(l,r-1)+1\)。结合之前的结论,若找到了满足条件的最大的\(l\),那么可以用一个区间加法操作更新所有需要更新的\(s_i\)。
到这里,这题的做法就比较明显了,枚举右端点,看是否可以用当前点扩展答案,若能扩展就是一个区间加法;然后回答所有右端点为当前端点的询问,也就是一个单点取值。这两个操作是树状数组或者线段树的基本操作,不再赘述。
总结
17min过了前3题,看了下排名是26,然后就开始自闭了
看到D题题面人傻了,本来博弈论就不太熟悉,还给整了个树上博弈,所以不太有信心做出来。仔细看了之后发现结论还是比较好推的,就是犯了低级错误疯狂WA on test2。