题解/算法 {5726. 连续子序列}
@LINK: https://www.acwing.com/problem/content/description/5729/
;
令sum[x] = A[0^...^x]
, 因为A[l^...^r] = sum[r] ^ sum[l-1]
, 因此 对于当前的r
我们将0, sum[0,1,...,r-1]
都放入Trie树里
然后此时根据sum[r]
去树里查询, 此时 就很考察你的逻辑思维能力了 不多说了 总之是分情况讨论 即比如当前查询的是x
(他是0/1
) 然后此时可能0,1
分支都存在 也可能只有1个存在, 此时很容易思路乱 一个核心思路是: 我们始终令当前的k < K
一旦比如你要走的分支 和x
不同 此时会导致k += ?
增加 那么一旦k >= K
就终止, 这样的话 即使01
两个分支都存在: @IF(当(k+?) >= K
){即此时x^1
这个分支不用走 直接把他的prefixCount
累加答案即可, 然后走x
分支 他不影响k
的值}–@ELSE{这个情况是最最难的 此时你一定是走x^1
这个分支 换句话说 答案只可能在x^1
这个分支 x
这个分支一定没有答案 这是因为x + (1<<b) < K
那么x + (1<<bi)之和 (其中bi<b)
也一定 < K
因此你只需要走x^1
这个分支};
int k = 0;
for( int len = 0; len <= Len; ++len){
//>< `curNode`代表`_str.substr(0,len)`这个字符串;
ASSERT_( k < K);
if( len < Len){
int id = ((_a>> (Len-1-len)) & 1);
vector<int> nex;
FOR_( son, 0, 1){
if( curNode->SonPtr[son] != nullptr){ nex.push_back(son);}
}
if( nex.size()==0){ return ANS;}
else if( nex.size() == 1){
k += ( (nex.front()==id ? 0:1) << (Len-1-len));
curNode = curNode->SonPtr[ nex.front()];
if( k >= K){
ANS += curNode->PrefixCount;
return ANS;
}
}
else{
if( (k + (1<<(Len-1-len))) >= K){
ANS += curNode->SonPtr[ id^1]->PrefixCount;
curNode = curNode->SonPtr[id];
}
else{
k += (1<<(Len-1-len));
curNode = curNode->SonPtr[id^1];
}
}
}
}
上面代码是对的, 但是很可惜… 他超时了 你怎么优化都超时 可能把现在的指针版本改成是数组下标方式 应该就可以了(不知道 没试过 以后看有没有必要 数组下标版本是不是各方面都比指针版本要好吖?)
一个补救措施是 你把vector<int> nex
给去掉把, 因为这个题常数确实太大了 N=1e6 * 30 = 3e7
太大了 是可以把nex
给去掉 直接用两个int
变量来替代 这也说明容器确实开销大; (同时你也还需要优化Trie
即普通优化 把Assert
去掉)
int k = 0;
for( int len = 0; len <= Len; ++len){
//>< `curNode`代表`_str.substr(0,len)`这个字符串;
ASSERT_( k < K);
if( len < Len){
int id = ((_a>> (Len-1-len)) & 1);
int cont = 0, tar;
FOR_( son, 0, 1){
if( curNode->SonPtr[son] != nullptr){ ++ cont; tar = son;}
}
if( cont==0){ return ANS;}
else if( cont == 1){
k += ( (tar==id ? 0:1) << (Len-1-len));
curNode = curNode->SonPtr[ tar];
if( k >= K){
ANS += curNode->PrefixCount;
return ANS;
}
}
else{
if( (k + (1<<(Len-1-len))) >= K){
ANS += curNode->SonPtr[ id^1]->PrefixCount;
curNode = curNode->SonPtr[id];
}
else{
k += (1<<(Len-1-len));
curNode = curNode->SonPtr[id^1];
}
}
}
}