题意:求n个非负数中任意2个的异或值的最大值。n数量级为10^5
分析:一个非负整数可以看成1个32位的01字符串,n个数可以看成n个字符串,因此可以建立字典树,建好树后,对于任意非负整数x,可以沿着树根往下贪心找到y,使得x异或y最大,复杂度为树的深度。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <math.h> 5 using namespace std; 6 #define M 3200010 7 #define N 100010 8 int n; 9 int v[N]; 10 int node; 11 int next[M][2]; 12 int end[M]; 13 void add(int cur,int k){ 14 memset(next[node],0,sizeof(next[node])); 15 end[node]=0; 16 //printf("next[%d][%d]=%d\n",cur,k,node); 17 next[cur][k]=node++; 18 } 19 int cal(int x){ 20 int i,k,cur=0; 21 for(i=30;i>=0;i--){ 22 k=((1<<i)&x)?0:1; 23 if(next[cur][k]) cur=next[cur][k]; 24 else cur=next[cur][1-k]; 25 } 26 return (x^end[cur]); 27 } 28 int main(){ 29 int i,j,k,x,cur; 30 int ans; 31 while(~scanf("%d",&n)){ 32 node=1; 33 memset(next[0],0,sizeof(next[0])); 34 for(i=0;i<n;i++){ 35 scanf("%d",&x); 36 v[i]=x; 37 cur=0; 38 for(j=30;j>=0;j--){ 39 k=((1<<j)&x)?1:0; 40 if(next[cur][k]==0) add(cur,k); 41 cur=next[cur][k]; 42 } 43 end[cur]=x; 44 } 45 for(ans=i=0;i<n;i++) 46 ans=max(ans,cal(v[i])); 47 printf("%d\n",ans); 48 } 49 return 0; 50 }
题目连接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1717
题意:给一个长度为n的整数序列,现在要你截取这个序列的一个前缀和一个后缀(前缀和后缀不能相交),使得前缀和后缀的异或值最大。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <math.h> 5 using namespace std; 6 #define M 4200010 7 #define N 100010 8 int n; 9 long long v[N]; 10 long long pre[N]; 11 long long suf[N]; 12 int node; 13 int next[M][2]; 14 void add(int i){ 15 long long k,cur,x; 16 x=pre[i]; 17 cur=0; 18 for(int j=42;j>=0;j--){ 19 k=((1LL<<j)&x)?1:0; 20 if(next[cur][k]==0) { 21 memset(next[node],0,sizeof(next[node])); 22 next[cur][k]=node++; 23 } 24 cur=next[cur][k]; 25 } 26 } 27 long long cal(long long x){ 28 long long i,k,cur=0,r=0; 29 for(i=42;i>=0;i--){ 30 k=((1LL<<i)&x)?0:1; 31 if(next[cur][k]) { 32 cur=next[cur][k]; 33 r|=1LL<<i; 34 } 35 else cur=next[cur][1-k]; 36 } 37 return r; 38 } 39 int main(){ 40 int i,j; 41 long long ans; 42 while(cin>>n){ 43 ans=0; 44 node=1; 45 memset(next[0],0,sizeof(next[0])); 46 for(i=1;i<=n;i++) cin>>v[i]; 47 pre[0]=pre[n+1]=suf[0]=suf[n+1]=0; 48 for(i=1;i<=n;++i) pre[i]=pre[i-1]^v[i]; 49 for(i=n;i>0;--i) suf[i]=suf[i+1]^v[i]; 50 add(0); 51 for(i=1;i<=n+1;i++){ 52 ans=max(ans,cal(suf[i])); 53 add(i); 54 } 55 cout<<ans<<endl; 56 } 57 return 0; 58 }
注意:有两个地方WA了,一个是题意说前缀后缀可以是空,另外一个是1LL而不是1,范围!!!!