今天的题也很难,目前只改出了两题。
T1:这题要用到一个叫线性基的工具。
首先我们发现3^b给予我们一个贪心的思路:一定是要优先满足b较大的列。
紧接着就有一个做法了:从大到小枚举b,判断计算当前b的最大贡献。如果b有+1而没有-1,那么就判断一下3^b是否可行。有-1而没有+1同理。注意有+1也有-1时两列都为0和两列都为1的情况是同理的,在这种情况下我们可以定义限制为两列异或起来的值为0。
至于判断当前情况是否可行,我们可以用线性基来做。具体做法就是用线性基判断一下当前的n个数能不能从中选出一些使得异或值为我们想要的数。
T2:题解待更新。
T3:这题是一个点分治。
首先套上点分治的模板,每一层就代表一维。
然后对于每一次找出的重心,我们把它的儿子分成大小相对均匀的两部分,设它们分别为A和B。
接着算出A和B中每一个点到重心的距离,接着指定A到重心的边权在当前这一维中乘1,B到重心的边权在当前这一维中乘-1。这样我们就保证了每一个A集合中的点到B集合中的点的距离是合法的。
接着我们先断掉重心到B的连边,然后递归处理A+重心;再断掉重心到A的连边,递归处理B+重心。这样一直处理下去,就保证了所有的点对都是合法的。
最后我们把每一位按照边的权值来求出最终的答案数组。
下面要证明这个方法是对的:
1、算出来的数组的正确性是有保证的,即不会出现max>dis的情况。关于这个我们可以分维讨论,在这之前或之后的差值都不会比边权的和大。这个很难讲,但是画一下图就明白了。
2、每一次至少分出n/3的大小,也就是说最多剩下n*2/3的大小,所以最终的维数不会超过16(即1000不断乘2/3直至为0的次数)。
注意+1或-1的边是有向的。