题意分析:给定一个a数组,找出一个k,使得将a数组分成很多个部分,每个部分有k个数,使得每个部分的按位或的值相等。
该题可使用二进制的拆分法,将每个数的二进制每一位都分别讨论,最后取满足所有部分的值的最小值
使用拆分法将每一个数的第i部分取出。代码如下
for(int i=26;i>=0;i--)
{
int len=0,ma=1;
for(int j=1;j<=n;j++)
{
if(a[j]>>i&1)
{
ma=max(ma,len+1);
len=0;
}
else len++;
}
ma=max(ma,len+1);
if(ma==n+1) continue;
res=max(res,ma);
}
len用来记录连续0的个数,ma记录第i部分中最优的解。
res记录的是总体上的最优解,最后输出res即可。
ac代码:
#include<iostream>
using namespace std;
const int N = 1e5+10;
int t,n;
void solve()
{
cin>>n;
int a[N];
for(int i=1;i<=n;i++) cin>>a[i];
int res=1;
for(int i=26;i>=0;i--)
{
int len=0,ma=1;
for(int j=1;j<=n;j++)
{
if(a[j]>>i&1)
{
ma=max(ma,len+1);
len=0;
}
else len++;
}
ma=max(ma,len+1);
if(ma==n+1) continue;
res=max(res,ma);
}
cout<<res;
}
int main()
{
cin>>t;
while(t--)
{
solve();
cout<<"\n";
}
return 0;
}
为什么最大的ma值就是答案?
拿最后一个样例举例,将它们都表示为二进制时
将它们划分为4个部分,找到他们每一部分的最长0串,将它加一,就是这一部分的最优解,接着找到所有部分的,最后得到总体的最优解就是所有部分的最长0串加1了,如果不取最长的话,那么会有些部分不满足。