二進制拆位(貪心)【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));
}
相關文章
相關標籤/搜索