[CodeForces] CF847 题解

A. Union of Doubly Linked Lists

Link-CF
Link-Luogu

【题目大意】

给你若干个双向链表,让你把它们连成一条。

【解题思路】

每次把一条链表的头连向另一条的尾,用一个变量维护一下链表的尾,直接做就做完了。


B. Preparing for Merge Sort

Link-CF
Link-Luogu

【题目大意】

给定一个元素互不相同序列 \(a\),每次可以取出 \(a\) 中最长的一个上升子序列,但要求包含 \(a\) 的第一个数,然后将这个子序列删掉。求每次取出来的数。

【解题思路】

我们维护每次取出来的子序列的末尾值 \(f\)

显然,这个值是单调递减的。因为如果有 \(f_i < f_j, i < j\),那么取第 \(i\) 条子序列时可以将 \(f_j\) 取走。

所以,对于数 \(a_i\),如果当前子序列一共有 \(l\) 条,分两种情况考虑:

  • \(a_i \leq f_l\),如果 \(a_i\) 比最小的末尾值还小了,这意味着,没有子序列可以在 \(a_i\) 加入后保持单调递增。这时,我们给 \(a_i\) 新开一个子序列。

  • 否则,\(a_i\) 可以加到子序列里。为了维护单调性,我们需要找到一个位置,使得 \(a_i\) 加入后,\(f\) 依然单调递减。形式化地,我们需要找到一个位置 \(j\),使得 \(f_{j - 1} > a_i\)\(a_i > a_j\),然后将 \(a_i\) 插入到第 \(j\) 条子序列的后面,并更新 \(f\) 数组。注意到 \(f\) 具有单调性,二分查找即可。

统计答案使用一个 vector。直接做就做完了。


C. Sum of Nestings

Link-CF
Link-Luogu

【题目大意】

称一个字符串为括号序列,当且仅当它仅由 () 构成。

称一个括号序列是合法的,有

  • 空串是一个合法括号序列
  • 如果 \(s\) 是合法括号序列,那么 \((s)\) 也是。
  • 如果 \(p\)\(q\) 都是合法括号序列,那么 \(pq\) 也是。

以上定义与你熟知的定义相同。

在一个合法的括号序列中,称一对括号有 \(t\) 对嵌套,当且仅当在这对括号之间有 \(t\) 对括号。

称一个合法的括号序列 有 \(t\) 对嵌套,当且仅当对于这个序列的每一对相互匹配的括号,它们的嵌套对数之和为 \(t\)

例如,合法的括号序列 ()(())\(1\) 对嵌套,而 (((())))\(6\) 对嵌套。

现在,你需要构造一个合法的括号序列,使得它一共有 \(n\) 对括号,\(k\) 对嵌套。

【解题思路】

注意到每次对于一个有 \(t\) 对括号的合法括号序列 \(s\) 中,括号序列 \((s)\) (即在 \(s\) 外面加一对括号)会比原序列 \(s\)\(t\) 对嵌套,多 \(1\) 对括号。而括号序列 \(s()\)(即在 \(s\) 后面加一对括号)会比 \(s\)\(1\) 对括号,但嵌套对数不变。

这样我们就有一种构造方案:

欲构造有 \(n\) 对括号,\(k\) 对括号嵌套的合法括号序列 \(s\)

  • \(n - 1 \leq k\)。记有 \(n - 1\) 对括号,\(k - n + 1\) 对括号嵌套的合法括号序列为 \(s^{\prime}\)。则有 \(s=(s^{\prime})\)
  • 否则,记有 \(n - 1\) 对括号,\(k\) 对括号嵌套的合法括号序列为 \(s^{\prime}\)。则 \(s=s^{\prime}()\)

构造的可行性显然。

这样,我们成功地将构造 \(s\) 的问题转化为构造 \(s^{\prime}\) 的问题,通过递归不难实现,直接做就做完了。


D. Dog Show

Link-CF
Link-Luogu

【题目大意】

\(n\) 盆狗粮编号为 \(1\)\(n\),它们从左到右排成一排,数轴上位置为 \(1\)\(n\)。第 \(i\) 盆狗粮,只有在 \(t_i\) 秒以后才能吃,吃了它获得的价值为 \(1\)。狗从数轴原点开始,每次移动 \(1\) 单位长度需要 \(1\) 秒,狗可以选择不吃,可以在原地停留或者往右走,求在 \(T\) 秒内能获得的最大价值(第 \(T\) 秒不能吃)。

【解题思路】

神仙贪心。

注意到这题有一个很好的性质:所有狗粮的价值都一样。

首先,对于第 \(i\) 盆狗粮,吃掉它需要在它这里停留 \(\max{(t_i - i, 0)}\) 秒,因为移动到它需要 \(i\) 秒,这样剩下的时间就是停留的时间。

但是,我们最多有 \(T\) 秒,所以狗最多在那里停留 \(T - i - 1\) 秒。为什么减 \(i\)?因为需要花费 \(i\) 秒移动到那里;为什么减一?因为第 \(T\) 秒不能吃。

那么为什么要计算停留时间呢?对于一个狗粮,如果要停留,显然不管在哪里停留都一样(当然不能是在该狗粮后面),于是我们只在意停留时间。

好,我们这里先说做法,等会再解释。

具体地,我们对于第 \(i\) 个狗粮,显然对于第 \(1\)\(i - 1\) 个狗粮,如果停留时间超过了 \(T - i - 1\) 那么就不能吃,否则就能吃。

注意到我们在枚举 \(i\) 时,\(T - i - 1\) 是递减的。于是,我们可以用大根堆来维护停留时间。如果堆顶大于 \(T - i - 1\) 那么就弹掉,直到堆顶小于这个值,然后再把在第 \(i\) 个狗粮停留的时间扔堆里。这时候,堆的大小就是现在的答案。总答案是所有这些答案的最大值。

好,那么现在有人会问:我现在把所有大于 \(T - i - 1\) 的停留时间都弹掉了,但是剩下的停留时间的可能大于 \(T - i - 1\),怎么办?

这个事情是这样的。我们总共的停留时间不是求和,而是求最大值。因为我们在前面的狗粮停留时,间接地,我们也等待了后面的狗粮。因为对于每个狗粮,时间流逝是一样的。其实这就是一个木桶原理(仔细读读题目,如果想看详细的去看 luogu 的)。

好了,这样真的直接做就做完了。这道题是道蓝题,代码只有 19 行。


E. Packmen

Link-CF
Link-Luogu


F. Berland Elections

Link-CF
Link-Luogu


G. University Classes

Link-CF
Link-Luogu

【题目大意】

给定 \(n\) 个长度为 \(7\) 的字符串,统计每一列 \(1\) 的个数。

【解题思路】

暴力统计即可,直接做就做完了。


H. Load Testing

Link-CF
Link-Luogu

【题目大意】

给一个数组 \(a\),问多少次对单个位置 \(+1\) 操作后,能将序列变成前一段严格递增,后一段严格递减(即单峰序列)。

【解题思路】

考虑维护两个数组 \(p_i\)\(q_i\),分别表示前 \(i\) 个数为严格递增或第 \(i\) 个数到第 \(n\) 个数为严格递减时位置 \(i\) 的最小值。

考虑计算这两个数组。对于前 \(i\) 个数,考虑正序递推。由于它们是严格递增,所以 \(p_i\) 最小为 \(p_{i - 1} + 1\)。但是只有 \(+1\) 操作,所以如果 \(p_{i - 1} + 1 < a_i\),那么就有 \(p_i = a_i\)。所以有递推式

\[p_i = \max{(p_{i - 1} + 1, a_i)} \]

同理,\(q\) 倒序递推即可。有递推式

\[q_i = \max{(q_{i + 1} + 1, a_i)} \]

考虑枚举最高点 \(i\)(即山峰),对于 \(i\) 前面的数可以前缀和计算需要几次 \(+1\),对于 \(i\) 后面的数后缀和计算,对于 \(i\) 这个数,取到的值为 \(\max{(p_i, q_i)}\),因为 \(i\) 既属于前面的严格递增序列,也属于后面的严格递减序列。这样直接做就做完了。

形式化的:

\(sa\)\(sb\) 分别为 \(a\) 的前缀和和后缀和数组,则有

\[sa_i = sa_{i - 1} + a_i \]

\[sb_i = sb_{i + 1} + a_i \]

\(sp\)\(sq\) 分别为 \(p\) 的前缀和数组和 \(q\) 的后缀和数组,则有

\[sp_i = sp_{i - 1} + p_i \]

\[sq_i = sq_{i + 1} + q_i \]

对于最高点 \(i\),有答案为

\[ans_i = (sp_{i - 1} - sa_{i - 1}) + (sq_{i + 1} - sb_{i + 1}) + (\max{(p_i, q_i)} - a_i); \]

注意需要特判整个序列严格单增或者严格单减的情况,有答案为

\[Ans = \min{(sp_n - sa_n, sq_1 - sb_1, \min_{2\leq i < n}{ans_i})} \]

\[Ans = \min{(sp_n - sa_n, sq_1 - sb_1, \min_{2\leq i < n}{(sp_{i - 1} - sa_{i - 1} + sq_{i + 1} - sb_{i + 1} + \max{(p_i, q_i)} - a_i)})} \]

这样就做完了。


I. Noise Level

Link-CF
Link-Luogu


J. Students Initiation

Link-CF
Link-Luogu


K. Travel Cards

Link-CF
Link-Luogu


L. Berland SU Computer Network

Link-CF
Link-Luogu


M. Weather Tomorrow

Link-CF
Link-Luogu

【题目大意】

给定一个 \(n\) 个数的数列,如果它为等差数列输出第 \(n + 1\) 项,否则输出第 \(n\) 项。

【解题思路】

注意到对于等差数列 \(a\)\(2 \times a_i = a_{i - 1} + a_{i + 1} (2 \leq i < n)\),直接做就做完了。

posted @ 2024-11-06 08:01  Eliauk_FP  阅读(187)  评论(0编辑  收藏  举报