提高组杂题训练做题记录

提高组杂题训练做题记录

*A [CF1763C] Another Array Problem

首先我们会去想贪心策略,但是每一次取最大值和最小值操作并不是最优的,所以需要改变策略。

注意到如果我们对同一操作执行两次,这个区间内所有数会变成 \(0\)。因此假如我们在序列的一段进行这个操作,就可以将 \(a_1\)\(a_n\) 变成 \(0\),此时用最大值和这两个位置进行操作就可以将整个序列变成最大值了。

发现上述操作在 \(n\ge 4\) 的时候是可行的,但是 \(n\le 3\) 的时候需要拿出来单独讨论。不过这部分就是简单的了,暴力枚举每一种情况即可。

^B [CF1775E] The Human Equation

发现我们每一次一定是取一段正负交替的序列进行操作,显然这样最优。那么此时在子序列上的操作应该形如 \(+1,-1,+1,-1\cdots\)。我们敏锐的发现这样做在前缀和上的影响是 \(+1,0,+1,0,\cdots\)。也就是说我们单次操作在前缀和上的影响就是选出若干个数 \(+1\)\(-1\)

而最后要使得原数组全部为 \(0\),就必须让前缀和数组全部为 \(0\)。那么分正负数考虑,正数每次减一,负数每次加一,于是正数的操作次数是最大的正数,负数的操作次数是绝对值最大的数的绝对值,所以答案即为两者之和。

^C [CF1290C] Prefix Enlightenment

考虑到题目中说任意三个子集没有交集,也就是说一盏灯最多存在于两个集合中。

这个时候我们发现,对于一盏灯,如果其初始状态为 \(0\),那么它所属的两个集合必恰选其一;否则这两个集合要么都选,要么都不选。考虑用连边来描述这个模型,具体的,我们将每一个集合拆成选或不选两种状态,然后将根据初始状态连边即可。这与 2-SAT 是一致的。

然后考虑并查集的每一个联通块,显然在这个联通块中我们只能选所有的同一种状态的点,所以并查集还需要维护两种状态对应的点的个数以及答案。由于这个连边是具有对称性的,所以我们最后算的答案要除以 \(2\)

最后还有一点,如果一盏灯只存在于一个集合中,那么它会和一个虚点相连。此时我们不能选第一种状态的节点,只能选第二种状态的节点,所以强制特判掉这种情况即可。

*D [CF1458D] Flip and Reverse

考虑将字符 1 看成 \(1\),字符 0 看成 \(-1\),然后做一遍前缀和。此时如果一个串 \([l,r]\) 可以被操作,说明 \(s_{l-1}=s_r\)。我们将 \(s_i\)\(s_{i+1}\) 连一条边,此时一个合法的字符串一定构成了一个环。

注意到对这样的一个串进行操作的本质就是将这个环倒着走一遍。但是其实倒着走的时候走过的每一条边也都一定在原图中存在过\(^{[1]}\),因此我们可以不管这个限制。那么我们从起点走,走出的一条欧拉路径就一定对应着原字符串的一个变换,所以单次贪心往小的字符走即可。

\(^{[1]}\):由于我们每一次走只会从 \(x\) 走到 \(x\pm 1\) 的位置,所以对于环上的一个点 \(x\),能走到 \(x+1\) 就说明 \(x+1\) 也能走到 \(x\),所以每一次反着走的边也在原图上存在。

E [CF1389F] Bicolored Segments

题意就是说选出的线段颜色不同的话不能相交,因此最后选出的线段放在数轴上一定是一段红一段蓝的。

那么这就是一个经典 dp 了,设 \(dp(i,0/1)\) 表示以 \(i\) 作为一段红色 / 一段蓝色的开头的最大值,转移方程为:

\[dp(i,0/1)=\max\{dp(j,1/0)+w_{j,i}\} \]

其中 \(w_{j,i}\) 表示区间 \([j,i)\) 中有多少条相应颜色的线段。那么这个东西可以直接扫描线得出,然后上面的式子就可以用线段树维护了。

F [CF1580D] Sequence

考虑到题目中有区间求 \(\min\) 的贡献,并且需要全部求和,想到在笛卡尔树上进行 dp。

\(dp(x,i)\) 表示在 \(x\) 节点的区间中选了 \(i\) 个数的贡献,那么分选根节点和不选根节点进行转移即可,复杂度是 \(O(n^2)\) 的。

G [CF1720D2] Xor-Subsequence (hard version)

\(O(n^2)\) dp 过于显然,考虑如何优化。发现这个转移是基于值域上的位运算的,考虑利用 01-Trie 优化 dp。

考虑到题目要求条件为 \(a_{b_i}\oplus b_{i+1}<a_{b_{i+1}}\oplus b_i\),所以想到拆位考虑。那么此时不难发现,我们可以钦定两个值的前 \(k\) 位的值相同,而 \(k+1\) 位不同。此时会发现,假如我们求出 \(a_{b_i}\oplus b_i\) 那么两个值依然满足前 \(k\) 位值相同而第 \(k+1\) 位不同。不过此时还需要满足 \(a_{b_i}\)\(b_{i+1}\) 的第 \(k\) 位不同才可以。

所以在 01-Trie 上维护出 \(a_i\oplus i\) 的信息,并在每一个节点维护 \(a_i\) 的第 \(k\) 位的值为 \(0/1\) 时的最大值即可。

*H [CF1876F] Indefinite Clownfish

考虑到两个序列必然有值域上重叠的部分,因此考虑枚举重叠数字出现的位置 \((p,q)\)。然后会发现如下性质:

  • \((p,q)\) 区间中的所有数字如果要选,则必然同属于一种序列。如果有一个数同时属于两个序列,那我们完全可以改为枚举这个数。
  • \((p,q)\) 区间中不存在 \(k\) 使得 \(a_p=a_k=a_q\),如果存在,将枚举的点换为 \((p,k)\) 仍然是可行的。

所以实际上有用的 \((p,q)\) 点对只有 \(O(n)\) 种,并且可以分四种情况:

  • \(p\) 属于上升序列,\(q\) 属于下降序列,\((p,q)\) 属于上升序列。
  • \(p\) 属于下降序列,\(q\) 属于上升序列,\((p,q)\) 属于上升序列。
  • \(p\) 属于上升序列,\(q\) 属于下降序列,\((p,q)\) 属于下降序列。
  • \(p\) 属于下降序列,\(q\) 属于上升序列,\((p,q)\) 属于下降序列。

此时 \(p,q\) 两边延伸的区间在值域上一定不交,所以可以直接二分左右边界,利用倍增查找即可。最后的问题在于判断条件,实际上由平均值相等和序列长度总和为 \(k\) 的要求可以简单推出两个区间最左边的值之差与最右边的值之差均为 \(\dfrac{k}2-1\),按照这个进行判断即可。

^I [CF193D] Two Segments

考虑扫描线,对于每一个 \(r\),维护出所有的 \(f(l,r)\),表示值域区间 \([l,r]\) 在原序列上被分成了多少个连续段。考虑从 \(r\to r+1\) 时如何维护,先假设所有的 \(f\) 都加上了 \(1\),然后找出 \(r\) 在原序列中的位置 \(p_r\),若 \(a_{p_r-1}<r\) ,则区间 \([1,a_{p_r-1}]\) 这一段的连续段个数都可以减一。\(a_{p_r+1}\) 同理。

统计答案就是统计 \(f(l,r)\le 2\) 的区间数量,维护出最小值、次小值及其对应个数即可。

J [AGC056C] 01 Balanced

与 D 题一样的思路,令 0\(1\)1\(-1\),则可以得到序列的 \(s\)。那么根据题目的限制可以得到如下条件:

  • \(s_r=s_{l-1}\)
  • \(|s_i-s_{i-1}|\le 1\)

发现这个条件与差分约束一模一样,所以直接跑一边差分约束即可。由于差分约束的性质,这样跑出来的 \(s_i\) 一定满足字典序最大,因此差分完后得出的序列字典序一定最小。

posted @ 2024-11-25 21:05  UKE_Automation  阅读(12)  评论(0编辑  收藏  举报