题目大意:
有两种操作,加入数,删除数,问每次操作后最大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;
}