• [NOI2014]起床困难综合症


    传送门

    这道题的思路还是蛮值得学习的。

    我们知道,位运算中每一位的运算都是独立的,如果想使得最后的值最大,越多位上是1越好,且所在位越高越好。

    因为已经知道初始值的范围,那么我们就可以用每一位全0和每一位全1预先处理出经过所有操作的每一位上的数。

    如果某一位上初始为1最后为1,那么这一位上初始值就应该为1

    如果某一位上初始为0最后为1,那么这一位上初始值就应该为0

    如果某一位上初始为1或0最后都为1,我们优先选0,选小一点,使得更可能在[0,m]的范围内,为后面的选择留有余地。

    #include<bits/stdc++.h>
    #define N 100003
    using namespace std;
    int n,m;
    int op[N],num[N];
    int count(int x)
    {
        for(int i=1;i<=n;++i)
        {
            if(op[i]==1) x=x&num[i];
            if(op[i]==2) x=x|num[i];
            if(op[i]==3) x=x^num[i];
        }
        return x;
    }
    char s[5];
    int main()
    {
        n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%s",s);
            scanf("%d",&x);
            num[i]=x;
            if(s[0]=='A')op[i]=1;
            if(s[0]=='O')op[i]=2;
            if(s[0]=='X')op[i]=3;
        }
        int zero=count(0);
        int one=0,tot=0;
        while(one<=m)
        {
            tot++;
            one=one*2;
            one=one+1;
        }
        one=count(one);
        int ans=0;
        for(int i=tot-1;i>=0;--i)//一位位处理 
        {
            if(!(zero&(1<<i))&&(one&(1<<i))&&(ans|(1<<i))<=m)//注意不要超出范围 
            ans|=(1<<i);
        }
        printf("%d
    ",count(ans));
    } 
    View Code
  • 相关阅读:
    bzoj4183: tree
    bzoj4389: ZYB and Trees
    bzoj3253: 改编
    uoj#274. 【清华集训2016】温暖会指引我们前行
    uoj#272. 【清华集训2016】石家庄的工人阶级队伍比较坚强
    uoj#11. 【UTR #1】ydc的大树
    uoj#29. 【IOI2014】Holiday
    uoj#187. 【UR #13】Ernd
    bzoj5019: [Snoi2017]遗失的答案
    bzoj5017: [Snoi2017]炸弹
  • 原文地址:https://www.cnblogs.com/yyys-/p/11225961.html
Copyright © 2020-2023  润新知