【NOI 2014】起床困难综合征 拆位+贪心

来源:互联网 发布:linux查看远程进程 编辑:程序博客网 时间:2024/05/01 00:09

分析

首先求出所有的situ[i][j]表示第i个二进制为j的情况下攻击的最后的值(0或1).
然后从最高位开始尽可能取1,分四类讨论.

代码

#include <cstdio>#include <cctype>const int N=100010;const int BIT=30;int n,m;int p[N][2];int situ[BIT][2];int cnt;int res;inline int read(void){    int x=0; char c=getchar();    for (;!isdigit(c);c=getchar());    for (;isdigit(c);c=getchar()) x=x*10+c-'0';    return x;}int query(int bit,int fir){    for (int i=1;i<=n;i++)        if (p[i][0]==1)            fir&=p[i][1]>>bit&1;        else        if (p[i][0]==2)            fir|=p[i][1]>>bit&1;        else        if (p[i][0]==3)            fir^=p[i][1]>>bit&1;    return fir;}int main(void){//  freopen("a.in","r",stdin);    char c; n=read(),m=read();    for (int i=1;i<=n;i++)    {        scanf("\n"); c=getchar(); p[i][0]=c=='A'?1:c=='O'?2:3;        p[i][1]=read();    }    for (int bit=0;bit<BIT;bit++)        for (int w=0;w<=1;w++)                situ[bit][w]=query(bit,w);    for (int bit=BIT-1;bit>=0;bit--)        if (!situ[bit][0]&&!situ[bit][1])            continue;        else        if (!situ[bit][0]&&situ[bit][1])            if ((cnt|1<<bit)<=m)                cnt|=1<<bit,res|=1<<bit;            else;        else        if (situ[bit][0]&&!situ[bit][1])            res|=1<<bit;        else        if (situ[bit][0]&&situ[bit][1])            res|=1<<bit;    printf("%d\n",res);    return 0;}

小结

涉及位运算的问题很多时候要拆位,然后使用贪心,或者用Trie等数据结构维护.

最优性问题的解决方法
①枚举检索(爆搜,数据结构加快,随机化)
②阶段性(贪心,动态规划)
③参数搜索(枚举,二分,单调)
④图论(网络流,最短路,MST)
⑤代数(线性规划,一些数学模型)

0 0
原创粉丝点击