1. 程式人生 > >[] 序列 /2018.10.27 {二進位制優化}

[] 序列 /2018.10.27 {二進位制優化}

題目

在這裡插入圖片描述

解題思路

我們可以發現,aorba\ or\ b 一定不會比aa或者bb要小,所以直接輸出最大的O(n)O(n)內的最大或值。 對於aandba\ and\ b是會越來越小的,所以長度為kk的區間一定是有最優解,此題的關鍵就在於處理這個O(30m)O(30m)複雜度的東西。 可以將這kk個數的區間看成num[i]num[i](第ii位的11的個數)的3030位陣列,若num[i]==mnum[i]==m就累加i(1<<j)i*(1<<j)

j)為答案,每次僅需將第imi-m個數二進位制下每位對應的11減去,加上新併入的數即可。

程式碼

#include<cstdio>
#include<iostream>
#define rr register 
using namespace std; 
int n,m,a[1000010],ma,mb,num[40];
void write(int x){ if (x/10) write(x/10); putchar(x%10+'0'); }
inline int maxx(int x,int y){if (x>y) return x; return y;}
inline int
read() { int p=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar(); return p; } int main() { n=read(),m=read(); for (rr int i=1;i<=n;i++) a[i]=read(),mb|=a[i]; for (rr int i=1;i<=m;i++) for (rr int j=0;j<=30;j++
) if ((a[i]&(1<<j))==(1<<j)) num[j]++; for (rr int i=m+1;i<=n;i++) { int k=0; for (rr int j=0;j<=30;j++) { if (num[j]==m) k+=(1<<j); num[j]-=((a[i-m]&(1<<j))==(1<<j)); num[j]+=((a[i]&(1<<j))==(1<<j)); } ma=maxx(ma,k); } write(mb); putchar(' '); write(ma); }