题目: http://lightoj.com/volume_showproblem.php?problem=1269
题意:
保证数字在32位内;
输出区间异或和最大/最小。
分析:
把前缀异或和插入trie树中;
对于查询最大值:尽量走不相同的边;
对于查询最小值:尽量走相同的边。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long llong;
const int tmax=50005*32;
int num,trie[tmax][2],_min,_max;
int val[tmax];
void insert(int x)
{
int u=0,id;
for(int i=31;i>=0;i--)
{
id=(x&(1<<i))>0;
if(trie[u][id]==0)
trie[u][id]=++num;
u=trie[u][id];
}
val[u]=x;
return;
}
void search(int x)
{
int u=0,id;
//min
for(int i=31;i>=0;i--)
{
id=(x&(1<<i))>0;
if(trie[u][id]==0) id^=1;
if(trie[u][id]==0) break;
u=trie[u][id];
}
if(val[u]!=-1) _min=min(_min,x^val[u]);
//max
u=0;
for(int i=31;i>=0;i--)
{
id=(x&(1<<i))>0;
id^=1;
if(trie[u][id]==0) id^=1;
if(trie[u][id]==0) break;
u=trie[u][id];
}
if(val[u]!=-1) _max=max (_max,x^val[u]);
return;
}
int main()
{
int T,tmp,sum,n;
scanf("%d",&T);
for(int kase=1;kase<=T;kase++)
{
_max=sum=num=0;
_min=2147483647;
memset(trie,0,sizeof(trie));
memset(val,-1,sizeof(val));
val[0]=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&tmp);
sum^=tmp;
_max=max(_max,sum);
_min=min(_min,sum);
search(sum);
insert(sum);
}
printf("Case %d: %d %d\n",kase,_max,_min);
}
return 0;
}