异或问题
时间限制:2000 MS内存限制:65536 KB
描述
问题很简单,现在有一个数组a1,a2,a3……an。你的任务就是找到一个连续子段[l,r],使得al^al+1^……^ar达到最大。
输入
多组输入,每组有两行。第一行有一个整数n(1<=n<=10^5),表示数组的元素个数。第二行有n个元素,依次表示数组的元素。(0<=ai<=10^6)
产量
每组输出一行,这行仅一个数字。表示最大的连续子段异或值。
5
1 2 3 4 5
5
2 3 2 3 2
7
3
思路:连续子段可以利用前缀和的思想 -- 这里是前缀^ 然后利用字典树的思想 注意只有一个数的时候查询前缀 所以先预先加入一个 0
ACcode:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[100010], ch[2800000][2], ans, clk;
void insert(int k)
{
int root = 0;
for (int i = 25; i >= 0; i--)
{
int s = ((1 << i)&k);
if (s)
{
if (ch[root][1] == 0)
{
ch[root][1] = ++clk;
ch[clk][0] = 0;
ch[clk][1] = 0;
}
root = ch[root][1];
}
else
{
if (ch[root][0] == 0)
{
ch[root][0] = ++clk;
ch[clk][0] = 0;
ch[clk][1] = 0;
}
root = ch[root][0];
}
}
}
int quary(int k)
{
int root = 0, cnt = 0;
for (int i = 25; i >= 0; i--)
{
int s = ((1 << i)&k);
if (s)
{
if (ch[root][0] != 0)
{
root = ch[root][0];
}
else
{
root = ch[root][1];
cnt += (1 << i);
}
}
else
{
if (ch[root][1] != 0)
{
root = ch[root][1];
cnt += (1 << i);
}
else
root = ch[root][0];
}
}
return k^cnt;
}
int main()
{
int n, x;
while (scanf("%d", &n) != EOF)
{
ans = 0;
clk = 0;
ch[0][0] = 0;
ch[0][1] = 0;
insert(0);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
a[i] ^= a[i - 1];
insert(a[i]);
}
for (int i = 1; i <= n; i++)
ans = max(ans, quary(a[i]));
printf("%d\n", ans);
}
return 0;
}