题意
给定一个长度为n的序列a[1],a[2],…,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or … or c[m]。请求出总费用的最小值。
1<=m<=n<=500000
分析
首先有一个很棒棒的结论,就是a xor b or b=a or b
然后我们把a变成前缀和的形式,那么问题就变成了从序列中选择m个数使其or起来最大。
逐位贪心即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=500005;
int n,m,vis[N];
LL a[N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]^=a[i-1];
LL ans=0;
for (LL i=(LL)1<<62;i;i>>=1)
{
int s=0;
for (int j=1;j<=n;j++)
if (!vis[j]&&!(a[j]&i)) s++;
ans<<=1;
if (s>=m&&!(a[n]&i))
{
for (int j=1;j<=n;j++)
if (!vis[j]&&(a[j]&i)) vis[j]=1;
}
else ans|=1;
}
printf("%lld",ans);
return 0;
}