Problem
Solution
f
(
b
,
n
)
=
max
i
=
0
n
(
(
b
1
⊕
b
2
⊕
.
.
.
⊕
b
i
)
+
(
b
i
+
1
⊕
b
i
+
2
⊕
.
.
.
⊕
b
n
)
)
f(b,n)=\max_{i=0}^n((b_1 \oplus b _2 \oplus...\oplus b_i)+(b_{i+1} \oplus b_{i+2} \oplus...\oplus b_n))
f(b,n)=i=0maxn((b1⊕b2⊕...⊕bi)+(bi+1⊕bi+2⊕...⊕bn))
转化一下
f
(
b
,
i
)
=
max
j
=
0
i
(
p
r
e
j
+
p
r
e
j
⊕
p
r
e
i
)
f(b,i)=\max_{j=0}^i(pre_j+pre_j\oplus pre_i)
f(b,i)=j=0maxi(prej+prej⊕prei)
题目就转化为了对于每个
i
i
i,求出一个最优的
j
(
j
<
i
)
j(j<i)
j(j<i)
我们思考一下对于一定的
x
x
x,
y
y
y要怎么样
y
+
y
⊕
x
y+y\oplus x
y+y⊕x最大
对二进制下的单独一位进行考虑,会发现式子的真值表是这样的
x\y | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 1 |
那么每一位都是独立的,从高到低贪心即可。那么我们就需要查询在是否存在一个
p
≤
i
p\leq i
p≤i且
p
r
e
p
pre_p
prep是前几位贪心结果的超集,用高维前缀和解决。
时间复杂度
O
(
(
v
+
n
)
log
v
)
O((v+n)\log v)
O((v+n)logv)
Code
#include <cstring>
#include <cstdio>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=300010,maxm=1100000;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,mx,l,N,ans,mi[25],a[maxn],f[maxm];
int main()
{
read(n);mi[0]=1;
for(int i=1;i<=20;i++) mi[i]=mi[i-1]<<1;
memset(f,0x3f,sizeof(f));
for(rg int i=1;i<=n;i++)
{
read(a[i]);a[i]^=a[i-1];
getmin(f[a[i]],i);getmax(mx,a[i]);
}
for(N=1;N<=mx;N<<=1) ++l;
for(int i=0;i<l;i++)
for(rg int j=0;j<N;j++)
if(!(j&mi[i]))
getmin(f[j],f[j|mi[i]]);
for(rg int i=1;i<=n;i++)
{
ans=0;
for(int j=l-1;~j;j--)
if(!(a[i]&mi[j])&&f[ans|mi[j]]<=i)
ans|=mi[j];
printf("%d\n",ans+(ans^a[i]));
}
return 0;
}