赛时想到了二分+trie但是却没有想到怎么维护啊
看到异或,可以想位运算,trie和异或基。跟位运算肯定没啥关系,而异或基是选任意多个数进行异或,trie是两个数进行异或,所以这道题目用trie
二分,考虑是否存在至少\(k\)个区间不超过\(mid\)
check函数:我们枚举区间的右端点\(r\),找到一个最大的\(l\)使得\(a_l⊕a_r≤mid\),那么如果区间左端点是\([1,l]\),肯定都可以被统计(当然区间左端点也可能是\([l+1,r-1]\),这种情况我们之后处理,先找出必要条件)
如何找到\(l\)?我们对trie树上的每一个点记录一个值表示这个点的子树所代表的\(a\)的最大的位置。将\(a_r\)与\(mid\)放在trie树上查找。此时trie树已经插入了\(a_1\) ~ \(a_{r-1}\),我们从高位到低位进行查找,假设我们当前查找到了第\(i\)位,且从第\(i+1\)位到最高位我们当前异或出来的数都与\(mid\)的第\(i+1\)位到最高位相同,那么对于第\(i\)位:
如果\(mid\)的这一位为\(1\),显然我们\(a_r\)的这一位同方向走到底的任何一个位置都可以,所以将同方向子树位置最大值记录在答案中,然后向反方向子树走一步
如果\(mid\)的这一位为\(0\),我们只能朝\(a_r\)的这一位同方向子树走
注意处理走的时候无解的情况
对每个\(r\)都处理完后,我们还要处理一下上面括号中说的情况。设\(f[i]\)表示以\(i\)为右端点,最大的左端点满足\([f[i],i]\)这个区间符合条件(也就是说\([f[i]+1,i]\)这个区间存在一对数使得异或值大于\(mid\)),假设\(1\) ~ \(i-1\)已经处理好了,那么对于新增加的\(i\),\(f[i]\)要么是之前我们找到的\(l\),要么是\(f[i-1]\),取最大值就好了
标签:子树,trie,mid,value,异或,端点,区间,array From: https://www.cnblogs.com/dingxingdi/p/18349305