考虑离线求出每个数存在的区间,用时间线段树套链表维护每段区间内存在的数字。
然后从线段树根节点开始dfs,子节点的线性基=往父节点的线性基中插入子节点存在的数字后得到的线性基。
时间复杂度$O(31n\log n)$。
#include<cstdio>
#include<map>
std::map<int,int>vis,loc;
inline void read(int&a){
char c;bool f=0;a=0;
while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
if(c!='-')a=c-'0';else f=1;
while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
if(f)a=-a;
}
inline void up(int&a,int b){if(a<b)a=b;}
struct Base{
int a[31];
Base(){for(int i=0;i<31;i++)a[i]=0;}
inline void ins(int x){for(int i=30;~i;i--)if(x>>i&1){if(a[i])x^=a[i];else{a[i]=x;break;}}}
inline void ask(){
int t=0;
for(int i=30;~i;i--)up(t,t^a[i]);
printf("%d\n",t);
}
};
int n,i,x,c,d,v;
struct E{int v;E*nxt;}*g[1048577],pool[8000000],*cur=pool,*p;
void ins(int x,int a,int b){
if(c<=a&&b<=d){p=cur++;p->v=v;p->nxt=g[x];g[x]=p;return;}
int mid=(a+b)>>1;
if(c<=mid)ins(x<<1,a,mid);
if(d>mid)ins(x<<1|1,mid+1,b);
}
void dfs(int x,int a,int b,Base c){
for(p=g[x];p;p=p->nxt)c.ins(p->v);
if(a==b){c.ask();return;}
int mid=(a+b)>>1;
dfs(x<<1,a,mid,c),dfs(x<<1|1,mid+1,b,c);
}
int main(){
for(read(n),i=1;i<=n;i++){
read(x);
if(x>0){if(!(vis[x]++))loc[x]=i;}
else{if(!(--vis[-x]))c=loc[-x],d=i-1,v=-x,ins(1,1,n);}
}
for(std::map<int,int>::iterator j=vis.begin();j!=vis.end();j++)if(j->second)c=loc[j->first],d=n,v=j->first,ins(1,1,n);
return dfs(1,1,n,Base()),0;
}