传送门biu~
对b序列求前缀亦或和a[],求对于每一个i,a[i]^a[j]+a[j]的最大值。可以把每个a[i]看成各个二进制位的集合。
对于第i个前缀a[i],考虑a[i]每一个二进制位对答案的贡献。如果a[i]的第j位为1,那么这一位对答案的贡献一定为1;如果a[i]的第j位为0,那么这一位对答案的贡献可能是0或1+1=2。
对于一个数state,令f[state]表示state的超集(state的超集即所有包含state集合的所有集合)中的所有等于某个a[]的元素里,a[]数组下标最小的那个。
对于每一个i,贪心从最高位向低位找非0位并尽量将这个点的贡献变成2,维护一个state表示已经确定的哪些位的贡献变成了2,在state的超集中选满足条件的,这样贪心选取一定是最大的,最后输出a[i]+(state<<1),因为state每一位的贡献为2。
#include<bits/stdc++.h>
#define N 300005
#define M 2000005
using namespace std;
int n,a[N],f[M];
int main(){
memset(f,127,sizeof(f));
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
a[i]^=a[i-1];
f[a[i]]=min(f[a[i]],i);
}
for(int i=19;i>=0;--i){
for(int state=1;state<(1<<20);++state)
if(!(state&(1<<i)))
f[state]=min(f[state],f[state|(1<<i)]);
}
for(int i=1;i<=n;++i){
int state=0;
for(int j=19;j>=0;--j)
if(!(a[i]&(1<<j)) && f[state|(1<<j)]<=i) state|=1<<j;
printf("%d\n",a[i]+(state<<1));
}
return 0;
}