就是带删除的线性基,考虑对时间分治,就是按时间建线段树,对于一个数,得到他的存在时间区间[l,r],然后对线段树上相应节点记录这个数。最后dfs线段树,在叶子节点求解。
但是我一开始T了,因为我对于每个数[1,n],都重新dfs了一遍,就导致时间复杂度较大。其实可以在dfs中传参线性基。
1 //考虑对时间分治,就是按时间建线段树,对于一个数,得到他的存在时间区间[l,r],然后对线段树上相应节点记录这个数。最后DFS线段树,在叶子节点求解。 2 #include<iostream> 3 #include<cstdio> 4 #include<vector> 5 #include<map> 6 using namespace std; 7 int n,a[500010]; 8 map<int,int> l,r; 9 struct xxj 10 { 11 int b[33]; 12 void clear(){for(int i=0;i<=32;i++)b[i]=0;} 13 bool ins(int x) 14 { 15 for(int i=31;i>=0;i--) 16 if(x&(1<<i)) 17 { 18 if(!b[i]){b[i]=x;break;} 19 else x^=b[i]; 20 } 21 if(x)return 1; 22 else return 0; 23 } 24 int findmax() 25 { 26 int ans=0; 27 for(int i=31;i>=0;i--) 28 ans=max(ans,ans^b[i]); 29 return ans; 30 } 31 }ans[500010]; 32 struct tree 33 { 34 int l,r; 35 vector<int> sum; 36 #define l(x) tr[x].l 37 #define r(x) tr[x].r 38 #define sum(x) tr[x].sum 39 }tr[3000010]; 40 int cnt,root; 41 42 int build(int L,int R) 43 { 44 int now=++cnt; 45 if(L==R)return cnt; 46 int mid=(L+R)>>1; 47 l(now)=build(L,mid); 48 r(now)=build(mid+1,R); 49 return now; 50 } 51 void add(int l,int r,int L,int R,int x,int z) 52 { 53 if(L==R){sum(x).push_back(z);return;} 54 if(L>=l&&R<=r){sum(x).push_back(z);return;} 55 int mid=(L+R)>>1; 56 if(l<=mid)add(l,r,L,mid,l(x),z); 57 if(r> mid)add(l,r,mid+1,R,r(x),z); 58 } 59 void dfs(int x,int L,int R) 60 { 61 for(int i=0;i<sum(x).size();i++) 62 for(int j=L;j<=R;j++) 63 ans[j].ins(sum(x)[i]); 64 if(L==R)return; 65 int mid=(L+R)>>1; 66 dfs(l(x),L,mid); 67 dfs(r(x),mid+1,R); 68 } 69 signed main() 70 { 71 // freopen("in.txt","r",stdin); 72 73 cin>>n; 74 for(int i=1;i<=n;i++) 75 { 76 cin>>a[i]; 77 if(a[i]<0)r[-a[i]]=i-1; 78 else l[a[i]]=i; 79 } 80 root=build(1,n); 81 for(int i=1;i<=n;i++) 82 if(a[i]>0) 83 add(l[a[i]],r[a[i]]==0?n:r[a[i]],1,n,root,a[i]); 84 dfs(root,1,n); 85 for(int i=1;i<=n;i++) 86 printf("%d ",ans[i].findmax()); 87 }