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 }

 

posted @ 2012-08-18 13:12  凌云七风  阅读(266)  评论(0编辑  收藏  举报