CF1923 VP 记录
CF1923 VP 记录
AB 跳了。
C. Find B
赛时切了。
题意
如果存在一个整数数组 \(b\) 满足以下条件,则认为一个整数数组 \(a\) 是好的:
- \(|b|=|a|\)。
- \(a_i\neq b_i\)。
- \(\sum b=\sum a\)。
- \(b_i>0\)。
给定一个数组 \(c\),\(q\) 次询问,要求判断 \(c[l,r]\) 是不是好的数组。
可以做到 \(\Theta(n+q)\) 的复杂度。
做法
考虑一种构造方案,给所有数都减一,然后给最后一个数加上减去的总和。
这样显然是可行的。
但是可能有 \(1\),就不能减了。
所以 \(1\) 就得变成 \(2\)。
这样数字的总和可能就不够用了。
所以我们判断这种情况就好了。
所以我们的构造方案就是:把所有大于 \(1\) 的数减一,然后把所有 \(1\) 都至少加一。判断这样构造数字的总和够不够用即可,也就是区间中 \(1\) 的个数是否小于等于区间的和减去区间长度。
D. Slimes
赛时不会,跳了。
题意
有 \(n\) 个史莱姆一字排开。这些史莱姆按照从左至右的顺序编号为 \(1\) 到 \(n\),其中第 \(i\) 个史莱姆的大小为 \(a_i\)。
每隔一秒会发生以下情况:恰好有一个 史莱姆会吃掉它的一个邻居,并且将它的大小增加被吃掉的邻居的大小。一个史莱姆只有在其大小严格大于邻居时才能吃掉这个邻居。如果没有史莱姆的大小严格大于其任意一个邻居,则该过程结束。
例如,假设 \(n = 5\),\(a = [2, 2, 3, 1, 4]\)。过程可能如下进行:
首先,第 \(3\) 个史莱姆吃掉第 \(2\) 个史莱姆。第 \(3\) 个史莱姆的大小变为 \(5\),第 \(2\) 个史莱姆被吃掉。
接着,第 \(3\) 个史莱姆吃掉第 \(1\) 个史莱姆(由于第 \(2\) 个史莱姆已被吃掉,它们相邻)。第 \(3\) 个史莱姆的大小变为 \(7\),第 \(1\) 个史莱姆被吃掉。
然后,第 \(5\) 个史莱姆吃掉第 \(4\) 个史莱姆。第 \(5\) 个史莱姆的大小变为 \(5\),第 \(4\) 个史莱姆被吃掉。
最后,第 \(3\) 个史莱姆吃掉第 \(5\) 个史莱姆(因为第 \(4\) 个史莱姆已经被吃掉,它们相邻)。第 \(3\) 个史莱姆的大小变为 \(12\),第 \(5\) 个史莱姆被吃掉。
对于每个史莱姆,计算在所有可能的过程演变中,该史莱姆被另一个史莱姆吃掉所需的最少秒数,如果不可能被吃掉,则报告“不可能”。
做法
我们分别考虑每一个史莱姆 \(i\)。它一定是被某一个与它相邻的史莱姆区间合并起来吃掉了。
考虑这个区间的性质:
- 这个区间的和大于 \(a_i\)。
- 这个区间中的元素不是两两不同
这个东西是充分的,因为可以用区间最大值把区间中史莱姆全吃掉然后吃掉 \(i\)。
题意就是要求一个最小的这样的区间。显然区间长度关于是否可行有单调性,二分一下就行了。
判断和很好维护,直接维护一个前缀和即可。判断值是否全部相同,我们考虑数组 \(b_i=[a_i=a_{i-1}]\) 的前缀和即可。
E. Count Paths
题意
给你一棵树,点有颜色,问有多少条路径满足:
- 起止节点颜色相同。
- 路径上没有与起止节点颜色相同的点。
做法
直接点分治即可。
我赛时想的是启发式遍历子树,\(O(n\log^2 n)\),应该也能过。
就是先用线段树合并维护出子树中有贡献的颜色的出现次数,然后启发式地遍历大小较小的子树即可。可以理解为重链剖分然后遍历轻子树,因为轻子树大小总和是 \(O(n\log n)\) 的,单次查询是 \(\Theta(\log n)\) 的,所以是 \(O(n\log^2 n)\) 的。
F. Shrink-Reverse
赛时没切。
题意
给你一个 01 串,你可以进行以下两种操作:
- 交换两个位置(不用相邻)。
- 去掉这个串的所有前导零,然后翻转整个串。
你要进行 \(k\) 次操作,问这个串转成二进制后最小是多少。
做法
性质1:不会进行超过两次 \(2\) 操作。
这个性质显然。
性质2:不会进行超过 \(1\) 次翻转操作。
考虑如果翻转一次之后 \(1\) 都连在一起了,那就不用动了。否则我可以用这一次操作把最高位挪到后面,这样是比翻转一次优的,因为最高位都更低了。
然后我们分类讨论这两种情况。
如果不翻转,我们直接贪心把最高位往最后放即可。
如果翻转,我们考虑我们不会做。因为翻转前后都会进行交换操作。
考虑我们最后形成的串是什么。
实际上就是把串翻转之后,找到一段区间,这个区间满足以下性质:
- 这个区间的长度足够容纳所有的 \(1\)。
- 这个区间外的 \(1\) 个数小于等于 \(k-1\)。
- 这个区间转换成二进制后最小。
我们先二分一个长度,check 这个长度的区间有没有满足前两个条件的区间。
有了长度之后,我们记录一下哪些区间是合法的,然后用后缀数组找到最小的即可。
感想
这场感觉打得比较烂。
考得也不是比较偏门,主要是要多动脑子。