[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
试题分析
线性基显然无法带删。
那么我们考虑可以令这题的操作变成只加不删的数据结构,线段树就可以做到。
按照时间顺序建线段树维护线性基即可。
线性基要用vector才能卡过去。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
//#include<cmath>
#include<algorithm>
using namespace std;
inline int read(){
int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int INF = 2147483600;
const int MAXN = 500010;
int N;
struct qe{
int x,tim;
}a[MAXN+1],b[MAXN+1];
struct data{
int u,v,val;
}in[MAXN+1];
bool cmp(qe a,qe b){if(a.x!=b.x) return a.x<b.x; return a.tim<b.tim;}
int A,D; vector<int> vec[MAXN<<2]; int sz;
bool vis[MAXN+1];
inline void Add(int rt,int x){
for(int i=0;i<vec[rt].size();i++) if((x^vec[rt][i])<x) x^=vec[rt][i];
if(x){ vec[rt].push_back(x);
for(int i=vec[rt].size()-1;i;i--) if(vec[rt][i]>vec[rt][i-1]) swap(vec[rt][i],vec[rt][i-1]);
} return ;
}
inline void update(int rt,int s){
for(int i=0;i<vec[s].size();i++) Add(rt,vec[s][i]); return ;
}
inline void insert(int rt,int l,int r,int L,int R,int x){
if(L<=l&&R>=r){Add(rt,x); return ;} int mid=(l+r)>>1;
if(L<=mid) insert(rt<<1,l,mid,L,R,x);
if(R>mid) insert(rt<<1|1,mid+1,r,L,R,x);
}
inline void Query(int rt,int l,int r,vector<int> v){
for(int j=0;j<vec[rt].size();j++){
int x=vec[rt][j];
for(int i=0;i<v.size();i++) if((x^v[i])<x) x^=v[i];
if(x){ v.push_back(x);
for(int i=v.size()-1;i;i--) if(v[i]>v[i-1]) swap(v[i],v[i-1]);
}
}
if(l==r){
int ret=0;
for(int j=0;j<v.size();j++) if((ret^v[j])>ret) ret^=v[j];//cout<<ret<<" "<<(ret^c[0][j])<<endl;
printf("%d
",ret);return ;
}
int mid=(l+r)>>1; Query(rt<<1,l,mid,v);
Query(rt<<1|1,mid+1,r,v);
return ;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
N=read(); int j=1;
for(int i=1;i<=N;i++){
int x=read();
if(x>0) a[++A].x=x,a[A].tim=i;
else b[++D].x=-x,b[D].tim=i;
} sort(a+1,a+A+1,cmp); sort(b+1,b+D+1,cmp);
for(int i=1;i<=D;i++){
while(a[j].x<b[i].x) ++j;
in[++sz].u=a[j].tim; in[sz].val=a[j].x;
in[sz].v=b[i].tim; vis[j]=true; ++j;
} for(int i=1;i<=A;i++)
if(!vis[i]) in[++sz].u=a[i].tim,in[sz].v=N+1,in[sz].val=a[i].x;
for(int i=1;i<=sz;i++)
insert(1,1,N,in[i].u,in[i].v-1,in[i].val);
vector<int> v;
Query(1,1,N,v);
return 0;
}