Codeforces Round 915 (Div. 2)

Begginer’s Zelda

题目

输入一颗树,输出执行的最少操作次数,使得该树只有一个节点。每次操作可以选择树中的两个节点,将它们之间的路径压缩为一个节点,所有连接路径上节点的边都会连向新节点。

数据范围:\(2\leq n\leq 10^{5}\),\(1\leq u_{i},v_{i}\leq n\),\(u_{i}\neq v_{i}\)。

思路

每次操作贪心的选择两个叶子节点(度数为 \(1\) 的节点都看作叶子),根据叶子节点的数量 \(x\) 的奇偶性分类讨论:

  • 如果 \(x\) 为奇数,\(x=1\) 需要 \(0\) 次操作,\(x=3\) 需要 \(2\) 次操作,之后每增加两个叶子,都会使操作次数加 \(1\),由于数据范围限制初始时叶子至少有 \(2\) 个,所以操作次数为 \(\frac{x+1}{2}\)。
  • 如果 \(x\) 为偶数,\(x=2\) 需要 \(1\) 次操作,\(x=4\) 需要 \(2\) 次操作,之后每增加两个叶子,都会使操作次数加 \(1\),所以操作次数为 \(\frac{x}{2}\)。
  • 最后,可以将两种情况的公式合并为 \(\lfloor\frac{x+1}{2}\rfloor\)。

Largest Subsequence

题目

输入长度为 \(n\) 的字符串 \(s\),输出执行的最少操作次数,使得字符串有序。每次操作可以将字符串中字典序最大的子序列循环右移一位。

数据范围:\(1\leq n\leq 2\cdot 10^{5}\)。

思路

首先使用单调栈求出字典序最大的子序列(非严格单调递减),然后通过观察可以发现,执行多次操作最终会将该子序列反转。相当于求最少右移次数,使得子序列反转,该次数等于子序列长度减去子序列中最大字符的数量。其次,还需要判断子序列反转之后,字符串是否有序。

Cyclic MEX

题目

输入一个包含 \({0,1,2,\dots,n-1}\) 的排列 \(p\),输出排列 \(p\) 的所有循环移动的最大代价。对于数组 \(a\),它的代价为 \(\sum_{i=1}^{n}{\operatorname{mex}([a_{1},a_{2},\dots,a_{i}])}\)。

数据范围:\(1\leq n\leq 10^{5}\)。

思路

观察每循环左移一次,代价是如何变化的:

排列 \(2,3,6,7,0,1,4,5\) 对应的代价为 \(0,0,0,0,1,4,5,8\);

排列 \(3,6,7,0,1,4,5,2\) 对应的代价为 \(0,0,0,1,2,2,2,8\);

排列 \(6,7,0,1,4,5,2,3\) 对应的代价为 \(0,0,1,2,2,2,3,8\)。

可以发现每当将数 \(x\) 移动到排列末尾,所有大于 \(x\) 的 \(\operatorname{mex}\) 值都会变为 \(x\),然后 \(x\) 位置对应的 \(\operatorname{mex}\) 值为 \(n\)。

我们可以首先将排列移动为 \(1,4,5,2,3,6,7,0\) 形式,对应的代价为 \(0,0,0,0,0,0,0,8\)。然后使用单调递增栈维护左移的数构成的递增序列,栈中存储数的下标,模拟上述过程并维护最大代价。

第 375 场力扣周赛

统计最大元素出现至少 K 次的子数组

题目

输入长度为 \(n\) 的数组 \(a\) 和整数 \(k\),输出满足 \(\max(a)\) 至少出现 \(k\) 次的子数组的数目。

数据范围:\(1\leq n\leq 10^{5}\),\(1\leq k\leq 10^{5}\)。

思路

首先计算出最大值,然后将所有最大值的下标放入列表 \(l\) 中,最后枚举右端点即可。假设列表的长度为 \(m\),当前枚举到 \(i\),当 \(i<m-1\) 时,区间 \([l[i],l[i+1]-1]\) 范围内的右端点都对应 \(l[i-k+1]+1\) 数量的左端点,将它们相乘加入答案。特别的,当 \(i=m-1\) 时,取区间 \([l[i],n-1]\)。PS:也可以滑动窗口,使窗口内只包含 \(k-1\) 个最大值,这样计算答案的空间复杂度为 \(O(1)\)。

统计好分割方案的数目

题目

输入长度为 \(n\) 的数组 \(a\),输出将数组分割为若干不相交子数组的方案数。不相交表示子数组之间没有相同的元素,答案对 \(10^{9}+7\) 取余。

数据范围:\(1\leq n\leq 10^{5}\)。

思路

因为要求子数组之间没有相同元素,那么相同元素必定只会出现在一个子数组中,首先统计每个元素的最小和最大下标,这两个下标构成的区间是不可分割的。然后将所有不可分割的区间进行合并,最后剩余的区间数假设为 \(m\),那么就会有 \(2^{m-1}\) 种分割方案(因为 \(m\) 个区间有 \(m-1\) 个分割位置,每个分割位置有分割或者不分割两种状态)。PS:① 可以边计数边做乘法,不使用快速幂;② 可以只统计最大下标,然后遍历数组时维护最大下标的最大值,如果当前下标等于该值,那么就可以做一次分割。(代码

第 119 场力扣夜喵双周赛

消除相邻近似相等字符

题目

输入长度为 \(n\) 的字符串 \(s\),输出所需的最少操作次数,使得字符串 \(s\) 中的相邻字符在字母表中的距离大于 \(1\)。每次操作可以将字符串 \(s\) 中的某个字符修改为任意字符。

数据范围:\(1\leq n\leq 100\)。

思路

思路一:距离大于 \(1\) 的相邻字符可以将字符串 \(s\) 分割为若干子串,每个子串所需的最少操作次数为 \(\lfloor\frac{l}{2}\rfloor\),其中 \(l\) 表示子串的长度。

思路二:如果相邻字符距离小于等于 \(1\),那么贪心的修改右边的字符即可。

两种思路原理是一样的,只是实现时略有不同。

关闭分部的可行集合数目

题目

输入整数 \(n\) 表示有 \(n\) 个节点,长度为 \(m\) 表示无向边的数组 \(e\)(包含重边),以及整数 \(d\)。输出删除节点的方案数,使得剩余节点两两之间的最短路不超过 \(d\)。

数据范围:\(1\leq n\leq 10\),\(0\leq m\leq 1000\)。其他数据不会影响时间复杂度,所以不列出。

思路

题目要求满足条件的方案数,首先想到枚举所有方案,总共有 \(2^{n}\) 个方案,然后对每个方案求删除节点后的多源最短路(Floyd 算法),如果剩余节点两两之间的最短路都不超过 \(d\),那么答案就加一,总时间复杂度为 \(O(m+2^{n}n^{3})\)。因为是求最短路,所以重边可以只保留最小的那条边。