CF1556 - Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)

Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)

D. Take a Guess

题意

有一个长度为 NN 的序列每次你可以询问两个值的与值和或值,求出原序列中第k大值。

询问不能超过 2N2N 次。

思路

与位运算有关的恒等式请见blog中的这篇文章,下文使用了文章中一些恒等式。

a+b=(ab)+(a&b)a+b=(a|b)+(a\&b) 的直接应用。

如果有了 a+b,a+c,b+ca+b, a+c, b+c,那么很容易求出 a=(a+b)+(a+c)(b+c)2a = \frac{(a+b)+(a+c)-(b+c)}{2},而求每个 a+ba+b 只需要两次询问,所以先求出第一个元素,那么后面所有的元素,都可以通过两次询问得出,询问次数 2N2N 次。

这里还有更优的方法,只需要询问 5N3\frac{5N}{3} 次来自CF评论,还是考虑求出三元组:(a,b,c)(a, b, c),但只通过5次询问 a&b,ab,a&c,ac,b&ca\&b, a|b, a\&c, a|c, b\&c

先通过恒等式 a+b=(ab)+(a&b)a+b=(a|b)+(a\&b),求出 a+b,a+ca+b, a+c,再通过恒等式 ab=(ab)(a&b)a\oplus b = (a|b)\oplus(a\&b),求出 ab,aca\oplus b, a\oplus c

进一步可以求出来 bcb\oplus c,于是再通过恒等式 b+c=2(b&c)+(bc)b+c=2(b\&c)+(b\oplus c),可以得出 b+cb+c,于是我们就可以通过5次询问,获得 a,b,ca, b, c的值了!

下面代码所用的是 2N2N 次询问的做法:

E. Equilibrium

题意

给出两个长度为 nn 的序列 {an},{bn}\{a_n\}, \{b_n\},你可以进行如下操作:

  • 选择一个长度为偶数的严格单调递增序列:pos1<pos2<<pos2kpos_1 < pos_2< \cdots < pos_{2k}

  • {an}\{a_n\} 中对应下标为 pos1,pos3,,pos2k1pos_1, pos_3, \cdots, pos_{2k-1} 的数值都+1

  • {bn}\{b_n\} 中对应下标为 pos2,pos4,,pos2kpos_2, pos_4, \cdots, pos_{2k} 的数值都+1

接下来有 QQ 次询问,每次询问给出一个区间 [l,r][l, r],求能否用若干次上述操作,使得 ai=bi,lira_i=b_i, l\leqslant i\leqslant r

如果可以输出最小的操作次数,否则输出-1

思路

由于每次操作,对数组 a,ba, b 发生变化元素的个数和大小总是相同的,所以考虑将两者做差。

ci=biaic_i=b_i-a_i,若 cic_i[l,r][l,r] 上满足以下两个条件,则一定有解:

  • i=lrci=0\sum_{i=l}^r c_i=0

  • k[l,r],i=lkci0\forall k \in [l, r], \sum_{i=l}^k c_i \geqslant 0

第一个条件:因为每次 a,ba,b 数组同时进行+1,所以两者做差之和总是 00。优化方法,对 cc 数组求前缀和。

第二个条件:不妨假设 cl<0c_l < 0,这说明 al>bla_l > b_l,又由于第一个元素只能是+1,只会越加越大,所以不满足题意。优化方法,对 cc 数组的前缀和数组求区间最大值和区间最小值,记最大值为 MAX\text{MAX},最小值为 MIN\text{MIN},如果 MINsum[l1]<0\text{MIN}-sum[l-1] < 0 无解,否则答案即为 MAXsum[l1]\text{MAX}-sum[l-1],因为只需要将最大的一块减成 00 就能保证其他小块都减成 00 了。

用ST表求区间最值,时间复杂度 O(nlogn+Q)O(n\log n + Q)

H. DIY Tree

题意

给出 nn 个点的完全图,并给出每条边的边权,求该图的生成树,使得前 kk 的节点的度,不超过给定值,并要求整棵生成树的权值最小。(树的权值定义:树上所有边权之和。

数据范围:2n50,1kmin(n1,5)2\leqslant n\leqslant 50, 1\leqslant k\leqslant\min(n-1, 5)

思路

CF评论中学的模拟退火。

数据量较小。

  1. 先构造一个满足题意的生成树(比如所有节点都和 nn 节点连边)

  2. 用模拟退火算法,每次随机删除、随机添加有效边。

时间复杂度不会 ′(*>﹏<*)′

下面代码使用了多次退火,卡时5500ms过的,正确率还行。


CF1556 - Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)
https://wty-yy.github.io/posts/23754/
作者
wty
发布于
2021年8月31日
许可协议