USACO 6.1.3 Cow XOR
题目大意:
给出一个数列,求最大区间异或和。
异或和相同时取终点最靠前的,仍相同取最短的。
简单题解:
先求出前缀和。
对每个数,将其前一项的前缀和插入0-1树中。
然后在该树中,从高位到低位(贪心思想),查询与当前前缀和的各位尽可能不同的前缀。
然后更新答案。
我的代码:
1 /* 2 ID:t-x.h1 3 LANG:C++ 4 TASK:cowxor 5 */ 6 #include<cstdio> 7 #include<cstring> 8 FILE *fi=fopen("cowxor.in","r"),*fo=fopen("cowxor.out","w"); 9 const int MAXn=100000+9,MAXt=9*MAXn; 10 int a[MAXn]; 11 int next[MAXt][2],pos[MAXt],num=1; 12 int main() 13 { 14 int n,i,j,k,ans=0,ansx=1,ansy=1; 15 fscanf(fi,"%d",&n); 16 for(i=1;i<=n;++i) 17 { 18 fscanf(fi,"%d",a+i); 19 a[i]^=a[i-1]; 20 21 //插入前一项 22 for(k=1,j=20;j>=0;--j) 23 { 24 if(!next[k][(a[i-1]>>j)&1]) 25 next[k][(a[i-1]>>j)&1]=++num; 26 pos[ k=next[k][(a[i-1]>>j)&1] ]=i; 27 } 28 29 //查询当前项 30 31 for(k=1,j=20;j>=0;--j) 32 33 if(next[k][!( (a[i]>>j)&1 )]) 34 k=next[k][!( (a[i]>>j)&1 )]; 35 else 36 k=next[k][(a[i]>>j)&1]; 37 if(pos[k] && (a[i]^a[pos[k]-1])>ans) 38 ans=a[i]^a[pos[k]-1],ansx=pos[k],ansy=i; 39 } 40 fprintf(fo,"%d %d %d\n",ans,ansx,ansy); 41 fclose(fi); 42 fclose(fo); 43 return 0; 44 }