bzoj 4184 shallot
LINK:shallot
线性基 不过有动态删除和动态加入 考虑暴力复杂度过高。
不过我们可以将其离线 不难想到利用线段树分治来做 然后就做完了复杂度nlog^2.
值得一提的是 这里面有一个前置技能 :遍历map. 开迭代器 从 begin 到end 扫一遍即可。
同时扫到的某个位置 是map的内置pair 调用也同样用first 和second 调用。
这里在线段树撤销的时候 我采用的是开vector记录位置来撤销 当然我觉得把数组穿进去撤销时间开销觉得有点大。
因为我们撤销是根据以前的操作做的 所以这么做对以前的没有影响 所以是正确的。
const int MAXN=500010;
int n;
int f[32];
map<int,int>H;
vector<int>w[MAXN<<2];
map<int,int>::iterator it;
inline void change(int p,int l,int r,int L,int R,int x)
{
if(L<=l&&R>=r){w[p].pb(x);return;}
int mid=(l+r)>>1;
if(L<=mid)change(ls,L,R,x);
if(R>mid)change(rs,L,R,x);
return;
}
inline int insert(int x)
{
for(int i=30;i>=0;--i)
{
if(x&(1<<i))
{
if(!f[i]){f[i]=x;return i;}
else x=x^f[i];
}
}
return -1;
}
inline int ask()
{
int ans=0;
for(int i=30;i>=0;--i)
if((ans^f[i])>ans)ans=ans^f[i];
return ans;
}
inline void dfs(int p,int l,int r)
{
vector<int>g;
for(int i=0;i<w[p].size();++i)
{
int tn=w[p][i];
int mark=insert(tn);
if(mark!=-1)g.pb(mark);
}
if(l==r)
{
put(ask());
for(int i=0;i<g.size();++i)f[g[i]]=0;
return;
}
int mid=(l+r)>>1;
dfs(ls);dfs(rs);
for(int i=0;i<g.size();++i)f[g[i]]=0;
}
int main()
{
freopen("1.in","r",stdin);
get(n);
rep(1,n,i)
{
int x;get(x);
if(x<0)change(1,1,n,H[-x],i-1,-x),H[-x]=0;
else H[x]=i;
}
for(it=H.begin();it!=H.end();++it)if((*it).second)change(1,1,n,(*it).second,n,(*it).first);
dfs(1,1,n);return 0;
}