[BZOJ4245][ONTAK2015]OR-XOR:按位贪心

分析:

本校OI组交流时讲到的一道题,这道题很好地利用到了或与异或的性质。
按照按位贪心的思想从高位到低位贪心,发现只要有不少于m处的前缀异或和在该位为0,并且整个数列的异或和在该位也为0,那么这位就可以取到0。
为了不出现选取在更高位上不合法的位置划分,每处理完一位就把该位的前缀异或和改为(unsigned long long)-1(类似于打标记,不用更新之后的前缀异或和)。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
typedef unsigned long long LL;

inline LL read(){
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}

const int MAXN=500005;
int n,m;
LL a[MAXN],xsum[MAXN];

int main(){
    n=read(),m=read();LL ans=0;
    for(int i=1;i<=n;i++) xsum[i]=xsum[i-1]^(a[i]=read());
    for(int i=63;i+1;i--){
        int temp=0;
        for(int j=1;j<=n;j++)
            if(!((xsum[j]>>i)&1)) temp++;
        if(!((xsum[n]>>i)&1)&&temp>=m)
            {for(int j=1;j<=n;j++) if((xsum[j]>>i)&1) xsum[j]=-1;}
        else ans|=((LL)1<<i);
    }
    printf("%llu\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9665104.html