题解:
-
题目要求维护带插入和删除的整体异或最大值
-
整体异或最大值容易想到线性基,但线性基支持动态能插入而不支持删除。
-
可以发现每个数出现的时间是一段或几段连续的区间。
-
于是我们可以对时间建线段树,线段树的每个区间用$vector$储存在这段时间里出现的数,这样就避免了删除操作。
-
在统计答案时从线段树根节点遍历到叶子节点,同时维护一个线性基,将经过的节点$vector$中的数插入到线性基中,最后在叶子节点询问异或最大值即可。
查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+5;
const int mod = 1e9+7;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
struct LinearBasis
{
int a[32];
LinearBasis(){init();};
void init(){memset(a,0,sizeof(a));}
void Insert(int x){
for(int i = 30;i >= 0;--i){
if(!(x>>i&1))continue;
if(a[i])x^=a[i];
else {
for(int j = 0;j < i;++j){
if(x&(1<<j))x^=a[j];
}
for(int j = i+1;j <= 30;++j){
if(a[j]&(1<<i))a[j]^=x;
}
a[i]=x;
return;
}
}
}
int query(){
int ans = 0;
for(int i = 0;i <= 30;++i)ans^=a[i];
return ans;
}
void merge(const LinearBasis &b){
for(int i = 0;i <= 30;++i)Insert(b.a[i]);
}
};
map<int,int>mp;
int ans[maxn];
struct Segment_tree
{
vector<int>v[maxn<<2];
void Insert(int root,int l,int r,int il,int ir,int x){
if(l>=il&&r<=ir){
v[root].push_back(x);
return;
}
int mid = l+r>>1;
if(il<=mid)Insert(root<<1,l,mid,il,ir,x);
if(ir>mid)Insert(root<<1|1,mid+1,r,il,ir,x);
return;
}
void dfs(int root,int l,int r,LinearBasis lb){
for(auto i:v[root])lb.Insert(i);
if(l==r){
ans[l]=lb.query();
return;
}
int mid = l+r>>1;
dfs(root<<1,l,mid,lb);
dfs(root<<1|1,mid+1,r,lb);
}
}sg;
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in", "r", stdin);
freopen("simple.out", "w", stdout);
#endif
int n;
scanf("%d",&n);
for(int i = 1,a;i <= n;++i){
scanf("%d",&a);
if(a>0)mp[a]=i;
else {
sg.Insert(1,1,n,mp[-a],i-1,-a);
mp[-a]=0;
}
}
for(auto i:mp){
if(i.first>0&&i.second>0)sg.Insert(1,1,n,i.second,n,i.first);
}
LinearBasis lb;
sg.dfs(1,1,n,lb);
for(int i = 1;i <= n;++i)printf("%d\n",ans[i]);
return 0;
}