YbtOJ#20075区间异或
Posted stoorz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YbtOJ#20075区间异或相关的知识,希望对你有一定的参考价值。
题目
题目链接:http://noip.ybtoj.com.cn/problem/20075
思路
先做一遍前缀异或和,然后问题转化为序列中任选两个数异或起来不小于 (k)。
从高位到低位建立 Trie 树,分 (01) 计算答案即可。
时间复杂度 (O(Tnlog n))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000010,LG=30;
int Q,n,m;
ll ans;
int read()
{
int d=0; char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d;
}
struct Trie
{
int tot,c[N*LG][2],size[N*LG];
void ins(int v)
{
int p=1;
for (int i=LG;i>=0;i--)
{
int id=(v>>i)&1;
if (!c[p][id]) c[p][id]=++tot;
p=c[p][id];
size[p]++;
}
}
int query(int v)
{
int p=1,sum=0;
for (int i=LG;i>=0;i--)
{
int id=(v>>i)&1,id1=(m>>i)&1;
if (!id1) sum+=size[c[p][id^1]];
p=c[p][id^id1];
}
return sum+size[p];
}
void clr(int p)
{
if (c[p][0]) clr(c[p][0]);
if (c[p][1]) clr(c[p][1]);
size[p]=c[p][0]=c[p][1]=0;
}
}trie;
void prework()
{
ans=0; trie.tot=1;
trie.clr(1);
trie.ins(0);
}
int main()
{
freopen("xor.in","r",stdin);
freopen("xor.out","w",stdout);
Q=read();
while (Q--)
{
prework();
n=read(); m=read();
for (int i=1,x=0;i<=n;i++)
{
x^=read();
ans+=trie.query(x);
trie.ins(x);
}
printf("%lld
",ans);
}
return 0;
}
以上是关于YbtOJ#20075区间异或的主要内容,如果未能解决你的问题,请参考以下文章
luoguP3374ybtoj树状数组例题1单点修改区间查询
luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟