题意:给你n个数字,n个消除位置的顺序,问每次消除前不包含无效位置的区间的异或和的最大值。
题解:我们反向加入数字,那么每次会和pos-1与pos+1的区间合并,我们通过线性基记录每个位置的情况,通过并查集合并,查询合并完的线性基的最大异或和,就可以了。
AC代码:
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; struct L_B{ int d[61],p[61]; int cnt; L_B() { memset(d,0,sizeof(d)); memset(p,0,sizeof(p)); cnt=0; } bool insert(int val) { for (int i=30;i>=0;i--) if (val&(1<<i)) { if (!d[i]) { d[i]=val; break; } val^=d[i]; } return val>0; } int query_max() { int ret=0; for (int i=30;i>=0;i--) if ((ret^d[i])>ret) ret^=d[i]; return ret; } int query_min() { for (int i=0;i<=30;i++) if (d[i]) return d[i]; return 0; } void rebuild() { for (int i=30;i>=0;i--) for (int j=i-1;j>=0;j--) if (d[i]&(1<<j)) d[i]^=d[j]; for (int i=0;i<=30;i++) if (d[i]) p[cnt++]=d[i]; } int kthquery(int k) { int ret=0; if (k>=(1<<cnt)) return -1; for (int i=30;i>=0;i--) if (k&(1<<i)) ret^=p[i]; return ret; } }a[100005]; L_B merge(const L_B &n1,const L_B &n2) { L_B ret=n1; for (int i=30;i>=0;i--) if (n2.d[i]) ret.insert(n2.d[i]); return ret; } int mark[100005],ANS[100005],pre[100005],q[100005]; int find(int i){return i==pre[i]?pre[i]:pre[i]=find(pre[i]);} int main() { int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { int k; scanf("%d",&k); a[i].insert(k); pre[i]=i; } for(int i=1;i<=n;i++)scanf("%d",&q[i]); for(int i=n;i>=1;i--) { int k=q[i]; mark[k]=1; ans=max(ans,a[k].query_max()); if(mark[k-1]) { int t1=find(k-1),t2=find(k); pre[t2]=t1; a[t1]=merge(a[t1],a[t2]); ans=max(ans,a[t1].query_max()); } if(mark[k+1]) { int t1=find(k),t2=find(k+1); pre[t2]=t1; a[t1]=merge(a[t1],a[t2]); ans=max(ans,a[t1].query_max()); } ANS[i]=ans; } for(int i=1;i<=n;i++) printf("%d\n",ANS[i]); }