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;
}
posted @ 2020-03-21 18:40  chdy  阅读(149)  评论(0编辑  收藏  举报