奶牛异或 牛客

原题链接

考察: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 } 

 

posted @ 2021-01-02 09:01  acmloser  阅读(155)  评论(0编辑  收藏  举报