二进制拆位(贪心)【p2114】[NOI2014]起床困难综合症

Description

21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。做为一名青春阳光好少年,atm一直坚持与起床困难综合症做斗争。经过研究相关文献,他找到了该病的发病缘由: 在深邃的太平洋海底中,出现了一条名为drd的巨龙,它掌握着睡眠之精髓,能随意延长你们的睡眠时间。 正是因为drd的活动,起床困难综合症愈演愈烈, 以惊人的速度在世界上传播。为了完全消灭这种病,atm决定前往海底,消灭这条恶龙。历经千辛万苦,atm终于来到了drd所在的地方,准备与其展开坚苦卓绝的战斗。drd有着十分特殊的技能,他的防护战线可以使用必定的运算来改变他受到的伤害。具体说来,drd的防护战线由n扇防护门组成。每扇防护门包括一个运算op和一个参数t,其中运算必定是OR,XOR,AND中的一种,参数则必定为非负整数。若是还未经过防护门时攻击力为x,则其经过这扇防护门后攻击力将变为x op t。最终drd受到的伤害为对方初始攻击力x依次通过全部n扇防护门后转变获得的攻击力。ios

因为atm水平有限,他的初始攻击力只能为0到m之间的一个整数(即他的初始攻击力只能在 0, 1, … , m中任选,但在经过防护门以后的攻击力不受m的限制)。为了节省体力,他但愿经过选择合适的初始攻击力使得他的攻击能让drd受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使drd受到多少伤害。git

Input

输入文件的第 1 行包含 2 个整数,依次为n, m,表示 drd 有n扇防护门,atm 的初始攻击力为0到m之间的整数。spa

接下来n行,依次表示每一扇防护门。每行包括一个字符串op和一个非负整数t,二者由一个空格隔开,且op在前,t在后,op表示该防护门所对应的操做,t表示对应的参数。code

Output

输出一行一个整数,表示atm的一次攻击最多使drd受到多少伤害。ip

二进制相关,考虑拆位。字符串

这个题中,咱们要作的就是钦定初始攻击力,通过^&|操做以后获得的值最大。get

咱们从高位向低位枚举二进制每一位,判断加上当前位以后的答案是否会更优input

最后输出初始攻击力通过传送门以后的值便可。it

代码io

#include<cstdio>
#include<iostream>
#include<algorithm>
#define R register

using namespace std;

const int gz=1e5+8;

inline void in(R int &x)
{
    R int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

char op[15];

int t[gz],ans,n,m,ot[gz];

inline int c(R int x)
{
    for(R int i=1;i<=n;i++)
    {
        if(ot[i]==1)x&=t[i];
        else if(ot[i]==3)x^=t[i];
        else x|=t[i];
    }
    return x;
}

int main()
{
    in(n),in(m);
    for(R int i=1;i<=n;i++)
    {
        scanf("%s",op+1);
        if(op[1]=='A')ot[i]=1;
        else if(op[1]=='X')ot[i]=3;
        else ot[i]=2;
        in(t[i]);
    }
    for(R int i=30;~i;i--)
    {
        if((ans+(1<<i))>m)continue;
        if( c(ans) < c(ans+(1<<i)))
                ans+=(1<<i);
    }
    printf("%d",c(ans));
}
相关文章
相关标签/搜索