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
1 2 3 4 -2 -3
Sample Output
1
3
3
7
7
5
3
3
7
7
5
HINT
N<=500000,Ai<=2^31-1
不难发现,题目其实就是要求我们动态维护带插入和删除的线性基。
我们线段树分治一下,按时间建立线段树,一次插入对应有效的一段时间。
时间复杂度为O(Nlog^2N)。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } 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 maxn=500010; struct Set { int A[32]; Set() {memset(A,0,sizeof(A));} void insert(int val) { dwn(i,30,0) if(val>>i&1) { if(!A[i]) {A[i]=val;break;} val^=A[i]; } } int query() { int res=0; dwn(i,30,0) res=max(res,res^A[i]); return res; } }; int n,ls[maxn*2],rs[maxn*2],A[maxn],f[maxn],tmp[maxn],last[maxn]; int first[maxn*2],next[maxn*20],num[maxn*20],ToT,e,cnt; void build(int& o,int l,int r) { o=++ToT; if(l==r) return; int mid=l+r>>1; build(ls[o],l,mid);build(rs[o],mid+1,r); } void AddQuery(int o,int l,int r,int ql,int qr,int v) { if(ql<=l&&r<=qr) { num[++e]=v;next[e]=first[o];first[o]=e; } else { int mid=l+r>>1; if(ql<=mid) AddQuery(ls[o],l,mid,ql,qr,v); if(qr>mid) AddQuery(rs[o],mid+1,r,ql,qr,v); } } void solve(int o,int l,int r,Set G) { for(int i=first[o];i;i=next[i]) G.insert(num[i]); if(l==r) printf("%d\n",G.query()); else { int mid=l+r>>1;solve(ls[o],l,mid,G);solve(rs[o],mid+1,r,G); } } int main() { n=read();int rt=0; rep(i,1,n) tmp[i]=abs(A[i]=read()); sort(tmp+1,tmp+n+1); rep(i,1,n) last[i]=n+1; dwn(i,n,1) { int flag=1; if(A[i]<0) flag=-1,A[i]=-A[i]; A[i]=lower_bound(tmp+1,tmp+n+1,A[i])-tmp; f[i]=last[A[i]];last[A[i]]=i; A[i]*=flag; } build(rt,1,n); rep(i,1,n) if(A[i]>0) AddQuery(1,1,n,i,f[i]-1,tmp[A[i]]); Set T;solve(1,1,n,T); return 0; }