考虑离线求出每个数存在的区间,用时间线段树套链表维护每段区间内存在的数字。
然后从线段树根节点开始dfs,子节点的线性基=往父节点的线性基中插入子节点存在的数字后得到的线性基。
时间复杂度$O(31nlog 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 ",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; }