Educational Codeforces Round 126 (Rated for Div. 2)

比赛链接

A. Array Balancing

如果\(a_i > b_i\),那么就对换,反之不对换。

B. Getting Zero

一开始写递归发现死循环了,改成写BFS就能过。

C. Water the Trees

最后的状态会是所有元素都等于初始状态所有元素中的最大值。

然后二分。

D. Progressions Covering

从后往前删,每次让最后一个\(a_i < b_i\)的位置的\(a_i\)\(k\),这样会是最优的。

然后就是怎么维护的问题了,假设当前位于\(i\),之前在位置\(j >= i\)操作了\(p_j\)次,\([i, i + k - 1]\)内共操作了\(count\)次,这些操作对当前位置的影响为\(a_i = a_i +delta\),如果\(a_i < b_i\)\(i > k\),就让\(a_i\)\(k\)一直加到\(a_i \ge b_i\)

位置\(i\)操作完了就移动到位置\(i - 1\),对于位置\(i - 1\)\([i, i + k - 1]\)所有操作的影响都减了\(1\),所以\(delta = delta - count\),然后\(p_{i + k -1}\)不再有影响,所以\(count = count - p_{i + k - 1}\)。重复上一个操作。

注意对于\(1 \le i \le k\),内的元素,此时可能还不满足条件,这个时候只能令\(a_k\)去加\(k\),还需要的操作数很容易就能算。

E. Narrow Components

线段树经典题型,比赛的时候想出来了,但是手残半个小时没调出来,主要是合并区间的操作没写好。

其实就是线段树维护,每次合并左右两个区间的时候,左区间的右边界和右区间的左边界可能会连通,从而减少连通块的数量,所以左右区间合并的时候,先把两个区间的答案加起来,再讨论减少的情况。

有一个方法可以比较好的维护:对原本矩阵中的方格进行编号,然后对于每个区间维护3个值:区间答案\(ans\),3个左边界编号\(lmask\),3个右边界编号\(rmask\)。然后合并的时候就是并查集加边,如果\(lmask_i\)\(rmask_i\)都是有效的点,那么他们之间可以加边,如果成功加边就会使连通块数量减1。

F. Teleporters

对于一段长为\(l\)的段,加入\(k\)个点,这\(k\)个点肯定是尽量均分\(l\)代价降得更多,因为不均分的话那么把大的段匀1给小的段就可以使代价降低。假设\(f(l,k)\)是一个长度为\(l\)的段加入\(k\)个点之后的最小代价。

然后,会有\(f(l,k + 1) - f(l, k) \ge f(l, k + 2) - f(l, k + 1)\),也就是说一个段代价降低会越来越慢。连续的情况的话求个导就可以证了,但是题目要求是整数点,离散的话具体证明的话见证明

然后贪心地加降得多的可以借助二分搞,具体就是二分一个阈值\(c\),降低不低于\(c\)的点才加,这样就可以找到一个\(c\),使得只加入降低大于等于\(c\)点的之后代价小于等于\(m\),只加入降低大于等于\(c + 1\)的点之后代价大于\(m\)

然后对于一个固定的\(c\),对于初始的每一个段,需要找出刚好满足条件的\(k\),然后之前提到降低的代价随着\(k\)增加单调不增,所以可以二分求,这样加入的点的数量和降低之后的代价就有了,分别记为\(cost(c)\)\(count(c)\)

因为其实不需要把所有降低代价为\(c\)的都加进去,可能只加部分就足够了,所以还可以退回去一些操作。现在的代价是\(cost(c)\),但是有\(m - cost(c)\)是可以不优化的,所以\(\text{extra} = \lfloor \dfrac{m - cost(c)}{c} \rfloor\)个操作是可以回去的,即答案为\(count(c) - \text{extra}\)

posted @ 2022-04-10 16:30  _Backl1ght  阅读(108)  评论(0编辑  收藏  举报