有关or的最大/小值问题,一般都是从大往小贪心,后面的贪心不破坏前面贪心的结果。
对于这题同样从大往小按位考虑,只需要考虑前缀异或和。显然要使这一位为0,每段的末尾的前缀异或和必须均为0,且n的前缀异或和也为0。
如果这位上为0的前缀个数不到m则放弃这一位,否则将所有这一位为1的位置删去。最终结果一定是所求最小值。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 typedef long long ll; 5 using namespace std; 6 7 const int N=1000010; 8 int n,m; 9 ll ans,a[N]; 10 11 int main(){ 12 freopen("bzoj4245.in","r",stdin); 13 freopen("bzoj4245.out","w",stdout); 14 scanf("%d%d",&n,&m); 15 rep(i,1,n) scanf("%lld",&a[i]),a[i]^=a[i-1]; 16 for (int d=60; ~d; d--){ 17 int cnt=0; 18 if (a[n]&(1ll<<d)) { ans|=1ll<<d; continue; } 19 rep(i,1,n) if (~a[i] && !(a[i]&(1ll<<d))) cnt++; 20 if (cnt<m){ ans|=1ll<<d; continue; } 21 rep(i,1,n) if (~a[i] && a[i]&(1ll<<d)) a[i]=-1; 22 } 23 printf("%lld ",ans); 24 return 0; 25 }