题解 Codeforces div4 压轴题合集

这篇博客汇总了 CodeForces div4 赛事中的压轴题目,包括 Round #640 的 Special Permutation、Round #784 的 Maximal AND 等,通过深入解析算法思路,如动态规划和二进制位操作,为读者提供解题策略。文章详细介绍了每道题目的解题方法,如利用树状数组优化复杂度,以及如何构建特殊序列以达到最佳效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解 CodeForces div4 压轴题合集

1. Round #640 G - Special Permutation

link. code.

显然可以构造类似 1,4,2,5,3,6,9,7,10,8,... \texttt{1,4,2,5,3,6,9,7,10,8,...} 1,4,2,5,3,6,9,7,10,8,... 这样的序列循环,然后特判末 5 5 5 9 9 9 位。

但是有一种更简单的方法(后来想的,没写代码): 1,3,5,...,n-1,n-4,n,n-2,n-6,n-8,n-10,...,2 \texttt{1,3,5,...,n-1,n-4,n,n-2,n-6,n-8,n-10,...,2} 1,3,5,...,n-1,n-4,n,n-2,n-6,n-8,n-10,...,2

2. Round #784 H - Maximal AND

link. code.

记录每个二进制位出现过几次,优先填最高位。

3. Round #790 H2 - Maximum Crossings (Hard Version)

link. code.

每读入一个 a i a_i ai,用树状数组查询 [ a i , n ] [a_i,n] [ai,n] 的总和,并令第 a i a_i ai + 1 +1 +1

4. Round #799 H - Gambling

link. code.

首先,题意可以转化为:

求一个区间 [ l , r ] [l,r] [l,r],一个数 a a a,使得 ∑ i = l r [ x i = a ] − ∑ i = l r [ x i ≠ a ] \sum\limits_{i=l}^r[x_i=a]-\sum\limits_{i=l}^r[x_i\neq a] i=lr[xi=a]i=lr[xi=a] 最大。若有多组解输出任意一组。

那么首先考虑确定 a a a,那么把原序列等于 a a a 的数改为 1 1 1,不等于 a a a 的数改为 − 1 -1 1,就变成了一个最大子段和问题,可以 O ( n ) O(n) O(n) dp 求解。

如果枚举 a a a 呢?那么这题的复杂度就是 O ( n 2 ) O(n^2) O(n2),过不了。


怎么优化呢?在 dp 求解最大子段和的过程,我们可以把连续的 − 1 -1 1 段合并为一个数,这样只用在出现 1 1 1 的时候进行 dp。对于下标 i i i,在所有 a a a 中必然只会存在一个 1 1 1,即 a = x i a=x_i a=xi 的情况。所以我们只会 dp n n n 次。复杂度降至 O ( n ) O(n) O(n)

l s i ls_i lsi 表示使 k < i , x k = x i k<i,x_k=x_i k<i,xk=xi 的最大的 k k k,则状态转移方程为:

f i = max ⁡ ( f l s i − ( i − l s i − 1 ) , 0 ) + 1 f_i=\max(f_{ls_i}-(i-ls_i-1), 0)+1 fi=max(flsi(ilsi1),0)+1

输出方案的话可以记录下 f i f_i fi 是从哪个地方转移过来的。具体可以参考代码。


求解 l s i ls_i lsi 也很简单,在读入时用 map 预处理一下即可,复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)。所以总复杂度也为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

5. Round #806 G

link. code.

可以很快的写出一个 O ( n 2 ) O(n^2) O(n2) 的 dp,但是没啥用。

发现性质:最优解必定是用好钥匙开前面多少个箱,其它用坏钥匙开。即不存在一个使用好钥匙开的箱子,前面有箱子用坏钥匙开

然后计算出一个 g g g 数组, g i g_i gi 表示第 i ∼ n i\sim n in 号箱子全都用坏钥匙开能获得的金币数。答案即为:

max ⁡ i = 0 n ( ∑ j = 1 i a j + g i + 1 ) \max\limits_{i=0}^n \left(\sum_{j=1}^i a_j + g_{i+1}\right) i=0maxn(j=1iaj+gi+1)

6. Round #817 G

link. code.

首先,因为 a xor ⁡ 0 = a a\operatorname{xor} 0=a axor0=a,所以对于奇数的情况,可以转换为偶数的情况再在后面加一个 0 0 0

可以发现, a xor ⁡ ( 2 k − 1 − a ) = 2 k − 1 a\operatorname{xor}(2^{k}-1-a)=2^k-1 axor(2k1a)=2k1,因为 a a a 2 k − 1 − a 2^{k}-1-a 2k1a 在二进制位下的每一位都不同。所以我们设 p = 2 28 − 1 p=2^{28}-1 p=2281(这里的指数可以改成别的数,但尽量大一些),构造序列 1 , 2 , p − 1 , p − 2 , 3 , 4 , p − 3 , p − 4 , . . . 1,2,p-1,p-2,3,4,p-3,p-4,... 1,2,p1,p2,3,4,p3,p4,... 即可。

若序列的长度不是 4 4 4 的倍数,序列末尾还空出了两个,怎么办?可以放两个相等的数,然后第一个加上个 2 30 − 1 2^{30}-1 2301,再让序列的第二个元素也加上 2 30 − 1 2^{30}-1 2301 即可(这里的指数也是可以改的)。

程序的大致思路和本文相似,但是细节方面有些不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值