卧薪尝胆,厚积薄发。
Nikitosh And Xor
Date: Mon Jul 16 20:33:28 CST 2018 In Category: NoCategory

Description:

在数组 $A$ 中选出不重叠的两段分别求异或和再相加,最大化最终答案。
$1\le N \le 4\times10^5$

Solution:

记 $f[i]$ 表示前半部分右端点 $\le i$ 的最大值, $g[i]$ 表示右半部分左端点 $\ge i$ 的最大值,最后两部分合并,将前缀插入一棵 $trie$ 树中,每次查和它异或值最大的前缀,并更新 $f$ ,后缀同理。
记得最开始将 $0$ 插入 $trie$ 树中。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n;
#define MAXN 400010
int a[MAXN],f[MAXN],g[MAXN];
struct node
{
int tr[2];
}t[MAXN * 40];
int ptr = 0;
int newnode(){return ++ptr;}
int root = 0;
void insert(int k)
{
int cur = root;
for(int i = 30;i >= 0;--i)
{
if(t[cur].tr[((k >> i) & 1)] == 0)t[cur].tr[((k >> i) & 1)] = newnode();
cur = t[cur].tr[((k >> i) & 1)];
}
return;
}
int query(int k)
{
int cur = root;
int res = 0;
for(int i = 30;i >= 0;--i)
{
if(t[cur].tr[!((k >> i) & 1)] != 0)
{
cur = t[cur].tr[!((k >> i) & 1)];
res += (1 << i);
}
else cur = t[cur].tr[((k >> i) & 1)];
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
int presum = 0;
insert(0);
for(int i = 1;i <= n;++i)
{
presum = presum ^ a[i];
f[i] = max(f[i - 1],query(presum));
insert(presum);
}
memset(t,0,sizeof(t));ptr = 0;
int sufsum = 0;
insert(0);
for(int i = n;i >= 1;--i)
{
sufsum = sufsum ^ a[i];
g[i] = max(g[i + 1],query(sufsum));
insert(sufsum);
}
long long ans = 0;
for(int i = 1;i < n;++i)
{
ans = max(ans,(long long)f[i] + (long long)g[i + 1]);
}
cout << ans << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡