BZOJ 4184: shallot
题目大意:
有两种操作,加入数,删除数,问每次操作后最大xor和
题解:
每个数字出现的时间是一段区间
线段树维护线性基,区间插入
有人说卡内存,但是没发现哪里会爆内存。
代码:
#include<cstdio> #include<algorithm> #include<vector> #include<map> using namespace std; int a[4000005],b[4000005]; map<int,int> M; vector<int> tag[4000005]; void insert(int t,int l,int r,int x,int y,int key){ if (r<x || l>y) return; if (l>=x && r<=y){ tag[t].push_back(key); return; } int mid=(l+r)>>1; insert(t<<1,l,mid,x,y,key); insert(t<<1|1,mid+1,r,x,y,key); } void dfs(int t,int l,int r,int a[]){ for (int i=0; i<tag[t].size(); i++){ int x=tag[t][i]; for (int j=30; j>=0; j--) if (x&(1<<j)){ if (!a[j]){ a[j]=x; break; } x^=a[j]; } } int b[31],c[31]; for (int i=0; i<=30; i++) b[i]=a[i],c[i]=a[i]; if (l==r){ int ans=0; for (int i=30; i>=0; i--) if ((ans^a[i])>ans) ans=ans^a[i]; printf("%d\n",ans); return; } int mid=(l+r)>>1; dfs(t<<1,l,mid,b); dfs(t<<1|1,mid+1,r,c); } int main(){ int n; scanf("%d",&n); for (int i=1; i<=n; i++){ scanf("%d",&a[i]); M[a[i]]=i; } for (int i=1; i<=n; i++) if (a[i]>0) { if (!M[-a[i]]) M[-a[i]]=n+1; insert(1,1,n,M[a[i]],M[-a[i]]-1,a[i]); } dfs(1,1,n,b); return 0; }