BZOJ4184 shallot葱苗

Description

  小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏。
  每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且
  让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大。
  这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为Oi选手的你,你能帮帮他吗?
  你只需要输出最大的异或和即可,若小葱手中没有小葱苗则输出0。

Input

  第一行一个正整数n表示总时间;
  第二行n个整数a1,a2...an,若ai大于0代表给了小葱一颗数字为ai的小葱苗,否则代表从小葱手中拿走一颗数字为-ai的小葱苗

Output

  输出共n行,每行一个整数代表第i个时刻的最大异或和。

Sample Input

6

1 2 3 4 -2 -3

Sample Output

1

3

3

7

7

5

Hint

N<=500000,Ai<=2^31-1

这道题考个思路。

线性基不支持删除操作。

如果只有删除这个操作的话,我们不妨把它倒过来视为添加操作(注意,这个思想在很多题中都会用到),但是——

这是一道有添加和删除两个操作的题,我们可以离线来搞,于是又变成了区间xor最大值的模板题。

因为有内存限制,我们就只存数,用一个线性基来操作(时间是有序的)

#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
const int N = 5e5+10;
struct Linear_Basis{
	int p[33];
	inline void insert(int k){
		Red(i,31,0){
			if(!(k>>i))continue;
			if(!p[i]){p[i]=k;break;}
			k^=p[i];
		}
	}
	inline int Max(){
		int ans=0;
		Red(i,31,0)if((ans^p[i])>ans)ans^=p[i];
		return ans;
	}
}LB;
struct Tree{
	int L,r;
	vector<int>vec;
}t[N<<2];
struct SegMent{
	#define Ls v<<1
	#define rs v<<1|1
	inline void build(int v,int L,int r){
		t[v]=(Tree){L,r};
		t[v].vec.clear();
		if(L==r)return ;
		int Mid=L+r>>1;
		build(Ls,L,Mid),build(rs,Mid+1,r);
	}
	inline void update(int v,int L,int r,int k){
		if(L>t[v].r||r<t[v].L)return ;
		if(L<=t[v].L&&t[v].r<=r)return t[v].vec.push_back(k),void();
		update(Ls,L,r,k),update(rs,L,r,k);
	}
}stm;
int n;
map<int,int>save;
map<int,int>::iterator it;
inline void init(){
	scanf("%d",&n);
	stm.build(1,1,n);
	Inc(i,1,n){
		int x;scanf("%d",&x);
		if(x>0)save[x]=i;
		else {
			stm.update(1,save[-x],i-1,-x);//在哪一段加入的 
			save.erase(-x);//删除下标(第一维) 
		}
	}
}
inline void Query(int v,Linear_Basis xxj){
	for(int i=0;i<t[v].vec.size();++i)xxj.insert(t[v].vec[i]);
	if(t[v].L==t[v].r)return cout<<xxj.Max()<<"\n",void();
	Query(Ls,xxj),Query(rs,xxj);//考虑到是有序的,我们一次遍历所有区间,因为50w太大单个询问会t 
}
inline void solv(){
	for(it=save.begin();it!=save.end();++it)stm.update(1,it->second,n,it->first);//因为已经去掉了被删除的,所以留下的数以后都能用 
	Query(1,LB);
}
int main(){
	init();
	solv();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dancingz/article/details/81045294