CF2157G Isaac's Queries 题解
赛时卡 F 导致没看 G,然后第二天有人告诉我题面然后我随便胡了个做法然后过了?
痛失上紫机会。
异或考虑拆位,由于询问的是最高位考虑从高到低做。我们用
我们考虑一个询问实际上给了我们什么信息。假设对
的异或和为 。 - 对于任意
, 的异或和为 。
利用区间询问来确定序列信息和 AT_abc238_e 和 P5937 很类似。所以我们使用类似的方法。
由于询问相当于给了
考虑
。 - 对于任意
, 。
如果我们将每个
由于每两个点的异或和对应了原数组一个区间的异或和,我们最终的目标是让原数组每个区间的异或和已知,因此我们希望这张图的所有点联通。我们要想在两个点连边只能通过一次代价为区间长度的询问,显然我们希望用尽可能小的代价让整张图联通,因此我们可以跑一个最小生成树。对于异或和为
实际上,每个区间的异或和第
接下来说一下我对期望代价的粗略估计:
考虑每层保留到下一层的子图是什么样子的。显然,假设异或前缀和第
由于数据随机生成,我们认为每组的个数是差不多的。第
考虑最后的 MST 会长什么样子。显然就是每组的第一个和最后一个连边,然后中间每个点向两边离自己更远的点连边。
首先最长的边就是每组点的下标极差。考虑从
我们使用这样一个 python 代码估计代价的大小: 1
2
3
4
5
6
7
8
9
10
11
12
13total = 0
for i in range(0, 6):
n = 100
delta = (n - (1 << i)) / (n + (1 << i)) * n
print(delta)
ans = 0
ans += 1 / delta
for j in range(1, int((n / (1 << i)) / 2)):
ans += (1 / (delta / 2 + j)) * 2
print(ans)
total += ans * (1 << i)
print(total)
结果大概是
参考代码在这里。