奶牛异或 牛客
考察:Trie+位运算
错误思路1:
枚举端点异或,这样肯定TLE
错误思路2:
利用前缀和思想,区间[i,j]内异或 = sum[i-1]^sum[j],将所有sum值插入树中枚举一个点,另一个利用之前的sum xor的思想,但是这样是错的,我们要取sum的下标,但数据量大的时候存在相同的sum值,此时它们树上的末尾结点p是相同的,但下标不同,如果仅仅用map或者数组标记是无法得到正确的下标的
正确思路:
同样是前缀和思想,在插入sum[i]的值前,先查询树中和它有最大值的sum[j],这样保证了i是末尾下标,也不会有重复的下标不同的sum值
但要记得处理边界问题,即如果答案在1,6 sum不从0开始就会答案错误
注意: 此代码只能在牛客和AcWing过,在vj上不能通过,待以后修 2021.1.2
1 #include <iostream> 2 #include <cstring> 3 #include <map> 4 using namespace std; 5 const int N = 100010; 6 //unordered_map<int,int> um;出错原因:sum可能重复 7 int idx,son[N*20][2],sum[N],cnt[N*20]; 8 void insert_t(int x,int id)//如果插入的x与之前的sum相同得到的p也是相同的 9 { 10 int p = 0; 11 for(int i=22;i>=0;i--){ 12 int t = x>>i&1; 13 if(!son[p][t]) son[p][t] = ++idx; 14 p = son[p][t]; 15 } 16 cnt[p] = id; 17 } 18 int query(int x) 19 { 20 int p = 0; 21 for(int i=22;i>=0;i--){ 22 int t = x>>i&1; 23 if(son[p][1^t]) p = son[p][1^t]; 24 else p = son[p][t]; 25 } 26 return cnt[p]; 27 } 28 int main() 29 { 30 // freopen("in.txt","r",stdin); 31 // freopen("out.txt","w",stdout); 32 int n,maxn = -1,st,ed; 33 scanf("%d",&n); 34 insert_t(0,0); //插入0防止边界 35 for(int i=1;i<=n;i++){ 36 int x; scanf("%d",&x); 37 sum[i] = sum[i-1]^x;//异或前缀和 38 int id = query(sum[i]); 39 if((sum[id]^sum[i])>maxn){ 40 st = id+1; ed = i; 41 maxn = (sum[id]^sum[i]); 42 }else if((sum[id]^sum[i])==maxn){ 43 if(ed==i&&st<id+1) st = id+1; 44 else if(ed>i) ed = i, st = id+1; 45 } 46 insert_t(sum[i],i); 47 } 48 49 if(!maxn&&st>ed) st = ed; 50 printf("%d %d %d\n",maxn,st,ed); 51 return 0; 52 }