BZOJ 4184: shallot
Description
在某时刻加入或删除一个点,问每个时刻的集合中能异或出来的最大值是多少.
Sol
线段树+按时间分治+线性基.
按时间分治可以用 \(logn\) 的时间来换取不进行删除的操作.
把一个数字的存在时间挂在线段树的区间上,不超过 \(logn\) 个区间,所以总和不超过 \(nlogn\) 个节点信息.
然后从上往下走遍历整个线段树,每次到根节点统计一下答案,这里跟线性基有些不同,线性基转置矩阵就是普通的高斯消元,这时候维护线性基,每次插入一个数,更新的贡献,统计答案的时候从上往下贪心,选一个最大值,而不是回带...
Code
/************************************************************** Problem: 4184 User: BeiYu Language: C++ Result: Accepted Time:11256 ms Memory:37624 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 5e5+50; const int M = 35; int n; map< int,int > mp; LL pow2[M],ans[N]; struct Py { LL b[M]; Py() { memset(b,0,sizeof(b)); } void insert(int x) { for(int i=M-1;~i;i--) if(x&pow2[i]) { if(!b[i]) { b[i]=x;break; } else x^=b[i]; } } LL GetAns() { LL ans=0; for(int i=M-1;~i;i--) if((ans^b[i])>ans) ans^=b[i]; return ans; } }piyan; struct SegMentTree { vector< int > d[N<<2]; #define lc (o<<1) #define rc (o<<1|1) #define mid ((l+r)>>1) void insert(int o,int l,int r,int L,int R,int x) { if(L<=l && r<=R) return void(d[o].push_back(x)); if(L<=mid) insert(lc,l,mid,L,R,x); if(R>mid) insert(rc,mid+1,r,L,R,x); } void DFS(int o,int l,int r,Py py) { for(vector< int > ::iterator i=d[o].begin();i!=d[o].end();i++) py.insert(*i); if(l==r) return void(ans[l]=py.GetAns()); DFS(lc,l,mid,py),DFS(rc,mid+1,r,py); } }seg; inline int in(int x=0,char ch=getchar(),int v=1) { while(ch>'9' || ch<'0') v=ch=='-' ? -1 : v,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x*v; } int main() { n=in(); for(int i=1;i<=n;i++) { int x=in(); if(x>=0) mp[x]=i; else x=-x,seg.insert(1,1,n,mp[x],i-1,x),mp.erase(x); } for(map< int,int > ::iterator i=mp.begin();i!=mp.end();i++) if((*i).second) seg.insert(1,1,n,(*i).second,n,(*i).first); pow2[0]=1;for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1; seg.DFS(1,1,n,piyan); for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); return 0; }