题目链接:https://vjudge.net/problem/LightOJ-1269
利用前缀异或和的思想加01字典树
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN = 50000 + 10;
struct Trie
{
int ch[32 * MAXN][2]; //节点的边信息
int num[32 * MAXN]; //节点存储值的个数
LL value[32 * MAXN]; //节点存储的值
int node_cnt; //树中当前节点个数
void init() //树清空
{
node_cnt = 1;
memset(ch[0],0,sizeof(ch));
memset(num, 0, sizeof(num));
}
void Insert(LL x) //在字典树中插入 X
{
//和一般字典树的操作相同 将X的二进制插入到字典树中
int cur = 0;
for(int i = 32; i >= 0; --i)
{
int idx = (x >> i) & 1;
if(!ch[cur][idx])
{
memset(ch[node_cnt],0,sizeof(ch[node_cnt]));
ch[cur][idx] = node_cnt;
value[node_cnt++] = 0;
}
cur = ch[cur][idx];
num[cur]++;
}
value[cur] = x; //最后的节点插入value
}
void update(LL x, int d) //更新x的个数 d为浮动值
{
int cur = 0;
for(int i = 32 ; i >= 0 ; i--)
{
int idx = (x >> i) & 1;
cur = ch[cur][idx];
num[cur] += d;
}
}
LL Query(LL x, int dir) //在字典树中查找和X异或的最大值\最小值的元素Y 返回Y的值
{
int cur = 0;
for(int i = 32; i >= 0; --i)
{
int idx = (x >> i) & 1;
if(ch[cur][idx ^ dir] && num[ch[cur][idx ^ dir]]) cur = ch[cur][idx ^ dir];
else cur = ch[cur][idx ^ !dir];
}
return value[cur];
}
};
LL num[100005];
LL xors[100005];
Trie ts;
int main()
{
int T, CAS = 0;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
ts.init();
for(int i = 1 ; i <= n ; i++)
{
scanf("%lld", &num[i]);
xors[i] = xors[i - 1] ^ num[i];
}
ts.Insert(0); ///任何值与0异或都是它本身
LL mx = 0;
LL mi = 1e12;
for(int i = 1 ; i <= n ; i++)
{
LL t0 = ts.Query(xors[i], 0); ///找异或最小值
LL t1 = ts.Query(xors[i], 1); ///找异或最大值
mi = min(mi, t0 ^ xors[i]);
mx = max(mx, t1 ^ xors[i]);
ts.Insert(xors[i]);
// printf("%lld %lld##\n", mx, mi);
}
printf("Case %d: %lld %lld\n", ++CAS, mx, mi);
}
}