Description
Input
Output
Sample Input
input 1:
6 3
1 1 1 0 0 0
input 2:
6 3
1 1 0 1 0 0
input 3:
6 3
11 8 2 1 3 9
Sample Output
output 1
1 1
output 2
1 0
output 3
11 1
Data Constraint
Solution
首先要仔细观察题意和思考其内在本质,我们可以发现:
①:最大的或值一定是全选的(越多越好,反正不会变小),可以 O(N) 直接求出。
②:最大的与值一定是选 K 个(越少越好,多了又不会变大)。
那么如何求与值呢?枚举区间的左端点,在
O(K) 计算?不!这样的话总时间复杂度可能达到 O(N∗K) ,并不可取。
于是,我们就可以使用线段树,维护整个区间的与值。
那么我们在枚举区间的左端点时,就可以 O(logN) 查找区间的与值。
最终的时间复杂度就是 O(NlogN) ,可以通过本题。
Code
#include<cstdio>
using namespace std;
const int N=1e6+1,Mx=2147483647;
int f[N<<2],a[N];
int ans1,ans2,num;
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline void make(int v,int l,int r)
{
if(l==r)
{
f[v]=a[l];
return;
}
int mid=(l+r)>>1;
make(v<<1,l,mid);
make(v<<1|1,mid+1,r);
f[v]=f[v<<1]&f[v<<1|1];
}
inline void query(int v,int l,int r,int x,int y)
{
if(l==x && r==y)
{
num&=f[v];
return;
}
int mid=(l+r)>>1;
if(y<=mid) query(v<<1,l,mid,x,y); else
if(x>mid) query(v<<1|1,mid+1,r,x,y); else
{
query(v<<1,l,mid,x,mid);
query(v<<1|1,mid+1,r,mid+1,y);
}
}
int main()
{
int n=read(),k=read();
for(int i=1;i<=n;i++) ans1|=a[i]=read();
if(n<=100 || k<=10)
for(int i=1;i<=n-k+1;i++)
{
int s=Mx;
for(int j=i;j<i+k;j++) s&=a[j];
if(s>ans2) ans2=s;
}
else
{
make(1,1,n);
for(int i=1;i<=n-k+1;i++)
{
num=Mx;
query(1,1,n,i,i+k-1);
if(num>ans2) ans2=num;
}
}
printf("%d %d",ans1,ans2);
return 0;
}