array-value

赛时想到了二分+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]\),取最大值就好了

posted @ 2024-08-08 16:55  最爱丁珰  阅读(13)  评论(0)    收藏  举报