CF VP 记录

CF2066

A

脑筋急转弯好题!考虑是否全排列,两种情况分开处理。对于全排列的情况,我们可以去询问 1 和 \(n\) 然后看正反是否相同且路径长度大于等于 \(n-1\) 即可;否则我们就考虑不在序列中的一个数,这个数代表的点在 A 类图中一定没有出边,于是询问这个点和任意一个出现过的点即可。

B

首先考虑有多个 0 的情况一定是保留最前面的 0 最优,然后考虑只有一个 0 的时候,我们从 0 的位置开始往前扫,如果不合法那么说明我一定会进行一次修改。考虑如果不改 0 可能之后还有修改就不优了,如果修改了 0 那么后面一定全部合法,于是选择后者即可。

C

考虑一个朴素的 dp,设 \(f_{i,j}\) 表示操作完第 \(i\) 个数后,两个数相同,另外一个相对异或值为 \(j\) 的方案数。转移状态数是 \(\mathcal O(1)\) 的但是最后的状态可能很多,于是滚动数组然后用 map 存第二维即可。

D

对于计数题考虑找充要条件。考虑一个数字能填需要满足其前面还没有 \(c\) 个数大于它,注意这个限制是后缀的,所以我们考虑值域的前缀。对于 1 我们只能放在 \([1,c]\),以此类推,我们能够得到 \(i\) 能够放置的区间 \([1,c+\sum\limits_{j<i}\text{cnt}_j]\),其中 \(\text{cnt}_j\)\(j\) 的数量。于是我们可以对其考虑 dp,设 \(f_{i,j}\) 表示考虑到 \(i\) 填了 \(j\) 个数的方案数。转移考虑枚举 \(i\) 放了多少个,设为 \(k\),其上界是 \(\min(j,c)\)。此时我们能够知道 \(i\) 填数范围是 \([1,c+j-k]\),首先我们需要判断这个上界是否合法,因为可能存在已经给出的 \(i\) 的最右边不在区间内的情况。判断转移合法性之后就简单了,现在只需考虑填数的方案数即可。因为之前已经有 \(j-k\) 个数,于是还剩下 \(c\) 个空位,但是考虑到原来的序列本身还有一些数已经确定,于是还要减去这段前缀区间内 \(\ge i\) 的数的个数,设为 \(s\)。考虑我们需要将 \(k\)\(i\) 放进去,但是可能原来序列中也有一些 \(i\) 了,其数量设为 \(t\),那么我们的方案数就是 \(c-s\choose k-t\)。于是最后的 dp 式子就是:

\[f_{i,j}=\sum_{k\le\min(c,j)}f_{i-1,j-k}\times{c-s\choose k-t} \]

时间复杂度 \(\mathcal O(nmc)\)

E

考虑如果有两个相同重量的桶那么我们就能比较他们,并且比较了之后这两个桶里面的水我们就能自由调动了。假设我们现在有 \(x\) 的水能够自由调动,考虑如何拓展。思考不难发现有两种情况:

  1. \(x\ge a_i\),我们能够分出恰好 \(a_i\) 的水去比较,于是 \(a_i\) 也能用了。
  2. \(a_i<a_j,a_i+x\ge a_j\),于是我们考虑给少的分一些水然后就可以比较两个桶了,然后这两个桶的水就都能用了。

于是我们给 \(a_i\) 排序,从小到大考虑水,每次先找到两个相同的然后开始拓展。容易得到单次 \(\mathcal O(n)\) 的做法。现在考虑优化。

可以发现每次拓展了一个新的桶之后我们又可以多拓展很多桶,并且考虑上述两种拓展的方法其 \(x\) 的增长都是 \(\ge 2a_i\) 的。于是我们考虑倍增值域,更进一步,我们能够联想到一个东西,叫做倍增值域分块。现在考虑分块后如何拓展。

对于一个 \(2^k\le a_i<2^{k+1}\) 的桶,如果我们能够拓展出它,那么我们一定能够拓展整个块内的元素,证明上面已经提过就不赘述了。于是每次我们从小到大去扫这 \(\mathcal O(\log)\) 个块,分别去看两种方式是否存在一种能够拓展这个块内的一个元素即可。

具体的,我们考虑对于每个块维护两个 multiset 分别记录 \(a_i\)\(\Delta=a_{i+1}-a_i\),然后每次拿块内最小的去和 \(x\) 进行比较即可。注意块间的 \(\Delta\) 不要算漏即可。时间复杂度 \(\mathcal O(n\log V)\)

CF2115

B

首先倒着考虑每个操作,因为确定一个数不好做于是转化成确定一个数大于等于多少,然后判合法即可。

C

思考两种不同的操作在什么时候要做什么时候不做。对于闪耀,如果全局最小值大于 1 那么一定要做;对于普通,如果当前所有数都相同,我们做了之后可能没有我们等闪耀然后一直全局减更优,这里需要比较一下代价;否则就可以直接做普通的操作。

注意到我们考虑是否做操作取决于全局最小值,于是我们考虑 dp,然后记录最小值,于是有 \(f_{i,j}\) 表示还有 \(i\) 次操作,全局最小值为 j 的概率。转移比较困难考虑加入更多的限制。这里有个 trick,具体可以看这道题的题解。就是说我们记录了最小值后就只用考虑上面的东西。于是就可以正常写转移了:

\[f_{i,j,s=}\begin{cases} 1 & i\ge0\wedge j=1\wedge s=0\\ p\times f_{i-1,j-1,0}+(1-p)\times \max(f_{i-1,j-1,n-1},f_{i-1,j,0}) & i>0\wedge j>1\wedge s=0\\ p\times f_{i-1,j-1,s}+(1-p)\times f_{i-1,j,s-1} & i>0\wedge s>0\\ 0 & \text{Otherwise} \end{cases} \]

此时 dp 时间复杂度为 \(\mathcal O(nmV^2)\),会寄,考虑一个优化。就是说当我们的 \(s\) 第一次变成 0 的时候 \(s\) 的上界就是 \(n-1\) 了,所以我们去枚举 \(s\) 什么时候变成 0 第三维就只用考虑到 \(n\) 了。式子也比较简单:

\[ans=\sum_{s\ge i}(1-p)^s\times p^{i-s}\times{i-1\choose s-1}\times f_{m-i,\max(mi-i+s,1),0} \]

其中 \(mi\) 是全局最小值。但是你如果这么写会炸精度,所以我们需要递推前面的系数。递推考虑 \(g_{i,s}\) 表示前面那坨,于是我们拆组合数就可以 \(\mathcal O(1)\) 转移了。

D

二选一异或有点复杂,所以我们假设先选择 \(a\),然后再进行调整。于是每次调整都需要异或上 \(c_i=a_i \oplus b_i\),所以我们只关注是否调整。对于博弈双方我们肯定都会按位从高到低考虑,否则一定不优。若考虑到第 \(i\) 位,那么决定最后状态的一定是最后一个第 \(i\) 位为 1 的,假设为 \(x\),我们可以进行选与不选的决策来调整。每次简单判断一下即可。注意更新答案后要将 \(c_j\) 中最高位是 \(i\) 的给异或上 \(x\),这个表示如果这一位选进答案,那么 \(x\) 是否选择的状态就要改变。每次做完最高位会减一,所以没有后效性可以大胆写。

E

对于容量小的我们可以直接做普通的完全背包,如果容量很大我们就可以用一个 trick,具体见 P9140。简单来说就是我们可以在一定范围进行贪心,然后在最后调整。注意到贪心选择的物品可能不对所有点做贡献,因为我们是在 DAG 上做背包。所以我们可以钦定用哪个作为贪心点然后去拓展即可。

CF2129

B

因为是排列所以我们可以从小到大考虑每个数。对于一个数,如果不变那么贡献是前面比它大的数个数,如果改变那么贡献是后面比它大的数的个数,取最小值即可。

C

首先我们得找到一个确定的括号,这样我们才可以判断。因为题目保证至少有一个 ( 和一个 ) 所以字符串中至少有一个 () 或者一个 )(,考虑前者贡献为一,后者无贡献于是考虑二分找即可。这里需要用掉 \(1+\left\lceil\log_2n\right\rceil=11\) 次查询。

C1

考虑还有 500 多次查询所以我们每次确定 2 个位置即可。我们考虑一个形如下面的查询:

( ( i j ( j i

我们分讨一下 4 种取值对应的结果即可。

C2

我们尝试让每次询问确定更多的位置,考虑一组形如 (((iii 的查询,其取值要么是零要么是长度的一半,我们状压一下就可以每次查询 8 个位置,因为有 \(7+\sum_{i=0}^82^i=518\) 如果再大就超过限制了。这样一共需要查 \(11+\left\lceil n\over 8\right\rceil=136\) 次。

C3

上面我们考虑括号嵌套的查询,其实我们还可以让括号并排,这样能构造出形如下面的东西:

( i ( i ( i ( ( j ( j ( j ( ( k ( k ( k

每次一个位置所带来的贡献要么为零要么为 \(cnt\times(cnt+1) \over 2\),考虑构造出不同的 cnt 保证每种组合唯一。可以构造出如下的 cnt 序列:

1,2,3,5,7,10,15,21,30,43,61,87,123

最后我们一次查询能够确定 13 个位置,总询问次数为 :\(11+\left\lceil n\over 13\right\rceil=88\)

D

神秘计数题我们考虑先去寻找性质,然后通过性质入手。

我们先去考虑一个位置 \(i\) 被贡献的情况,不考虑其他位置,于是左右对称,我们考虑左边。首先染色的位置应该从远到近,否则就贡献不到当前考虑的位置。然后考虑我们贡献的上限能是多少。最近的位置肯定是 \(i-1\),下一个不能是 \(i-2\),因为这时我们 \(i-1\) 的贡献就会给 \(i-2\),于是下一个位置实际是 \(i-3\)。再下一个呢?经过实践我们发现是 \(i-7\)。发现了吗?每次能作贡献的最右端点形如 \(i-2^k+1\),所以每个位置的贡献上界是 \(\log\) 的。

然后我们考虑一个位置被填了后,左边的位置显然不能贡献到右边去了,所以一个问题就被简化成了子区间,于是我们肯定是往区间 dp 的方向思考。所以首先我们的状态有 \(f_{i,j}\) 表示区间 \([i,j]\) 的答案,但是显然这样没法进一步转移,所以我们需要增加限制。因为我们转移的时候肯定要去枚举那个划分的位置,考虑那个位置对外置位做的贡献以及那个位置得到贡献的情况。考虑新划分出来的两个子区间肯定对划分位置有贡献,于是我们重新定义 dp 状态。设 \(f_{i,j,x,y}\) 表示考虑到了区间 \([i,j]\) 并且区间内没有染色,但是 \(i-1\)\(j+1\) 已经被染色,区间对 \(i-1\) 的贡献为 \(x\),对 \(j+1\) 的贡献为 \(y\)

转移的时候我们枚举了划分位置 \(k\),考虑 \(k\) 对外置位的贡献。如果 \(k\) 在区间左半部分,那么会对 \(i-1\) 有 1 的贡献;否则对 \(j+1\) 有 1 的贡献。枚举的时候注意减掉。然后两个子区间对 \(k\) 的贡献就枚举一下即可。注意因为是统计排列数,考虑两个子区间独立,于是在排列中只要相对顺序正确即可,所以还要带一个组合数 \(j-i\choose k-i\)。最后转移就是 \(f_{i,j,x,y}\leftarrow f_{i,k-1,x't}\times f_{k+1,j,q,y'\times{j-i\choose k-i}}\)。时间复杂度 \(\mathcal O(n^3\log^3n)\)

E

发现单次的修改是简单的,但是跟边数有关。注意到 \(n,m\) 同阶于是考虑对 \(m\) 分块跑莫队。然后注意到正常用平衡树是 \(\mathcal O(q\sqrt m\log n)\) 的修改加上 \(\mathcal O(q\log n)\) 的查询,于是考虑值域分块平衡复杂度。注意如果直接按照度数分块可能出现很多点度数为零导致块长爆炸,于是我们按照度数加点数分块,于是就是 \(\mathcal O(q\sqrt{n+m})\) 的。

posted @ 2025-10-02 21:18  Lyrella  阅读(24)  评论(0)    收藏  举报