【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

題解:

最大異或和第一個想到的就是線性基。

由於線性基無法進行刪除操作,所以我們考慮離線。

我們可以以時間來建一棵線段樹,給每個線段樹的節點開一個vector,存儲這個節點所包含有哪些數。將每一次插入和刪除同一個數看做一個個的區間進行修改。注意要用到標記永久化。最後遍歷整棵線段樹,用線性基求出每一個時間的答案。具體請看代碼。

 

如果有誤在評論區吼一聲哦!

#include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,tot,a[500010],lsh[500010],head[500010],nxt[500010],last[500010];
vector<int>Seg[2000010];
struct xxj{
	int a[35];
	xxj(){
		memset(a,0,sizeof(a));
	}
	void insert(int x){
		for(int i=30;i>=0;i--){
			if(x&(1<<i)){
				if(a[i]){
					x^=a[i];
					if(!x)
						return;
				}
				else{
					a[i]=x;
					return;
				}
			}
		}
		return;
	}
	int getmax(){
		int ans=0;
		for(int i=30;i>=0;i--)
			if((ans^a[i])>ans)
				ans^=a[i];
		return ans;
	}
};
int rd(){
	int x=0,y=1;
	char c;
	do{
		c=getchar();
		if(c=='-')
			y=-y;
	}while(!isdigit(c));
	do{
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}while(isdigit(c));
	return x*y;
}
void update(int o,int l,int r,int L,int R,int v){
	if(L<=l&&r<=R){
		Seg[o].push_back(v);
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid)
		update(o<<1,l,mid,L,R,v);
	if(R>mid)
		update(o<<1|1,mid+1,r,L,R,v);
	return;
}
void Query(int o,int l,int r,xxj a){
	for(int i=0;i<Seg[o].size();i++)
		a.insert(Seg[o][i]);
	if(l==r){
		printf("%d\n",a.getmax());
		return;
	}
	int mid=(l+r)>>1;
	Query(o<<1,l,mid,a);
	Query(o<<1|1,mid+1,r,a);
	return;
}
int main(){
	memset(Seg,NULL,sizeof(Seg));
	n=rd();
	for(int i=1;i<=n;i++)
		lsh[i]=labs(a[i]=rd());
	sort(lsh+1,lsh+n+1);
	m=unique(lsh+1,lsh+n+1)-(lsh+1);
	for(int i=1;i<=n;i++){
		int d=lower_bound(lsh+1,lsh+m+1,labs(a[i]))-lsh;
		if(a[i]>0){
			if(!head[d])
				head[d]=last[d]=i;
			else{
				nxt[last[d]]=i;
				last[d]=i;
			}
		}
		else{
			update(1,1,n,head[d],i-1,-a[i]);
			head[d]=nxt[head[d]];
		}
	}
	for(int i=1;i<=m;i++){
		if(lsh[i]==lsh[i-1]||!head[i])
			continue;
		update(1,1,n,head[i],n,lsh[i]);
	}
	xxj o;
	Query(1,1,n,o);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章