1. 程式人生 > >BZOJ 3668: [Noi2014]起床困難綜合癥

BZOJ 3668: [Noi2014]起床困難綜合癥

return 選擇 algo strong 改變 med style 驚人的 amp

3668: [Noi2014]起床困難綜合癥

Description

21 世紀,許多人得了一種奇怪的病:起床困難綜合癥,其臨床表現為:起床難,起床後精神不佳。作為一名青春陽光好少年,atm 一直堅持與起床困難綜合癥作鬥爭。通過研究相關文獻,他找到了該病的發病原因:在深邃的太平洋海底中,出現了一條名為 drd 的巨龍,它掌握著睡眠之精髓,能隨意延長大家的睡眠時間。正是由於 drd 的活動,起床困難綜合癥愈演愈烈,以驚人的速度在世界上傳播。為了徹底消滅這種病,atm 決定前往海底,消滅這條惡龍。歷經千辛萬苦,atm 終於來到了 drd 所在的地方,準備與其展開艱苦卓絕的戰鬥。drd 有著十分特殊的技能,他的防禦戰線能夠使用一定的運算來改變他受到的傷害。具體說來,drd 的防禦戰線由 n

扇防禦門組成。每扇防禦門包括一個運算op和一個參數t,其中運算一定是OR,XOR,AND中的一種,參數則一定為非負整數。如果還未通過防禦門時攻擊力為x,則其通過這扇防禦門後攻擊力將變為x op t。最終drd 受到的傷害為對方初始攻擊力x依次經過所有n扇防禦門後轉變得到的攻擊力。由於atm水平有限,他的初始攻擊力只能為0到m之間的一個整數(即他的初始攻擊力只能在0,1,...,m中任選,但在通過防禦門之後的攻擊力不受 m的限制)。為了節省體力,他希望通過選擇合適的初始攻擊力使得他的攻擊能讓 drd 受到最大的傷害,請你幫他計算一下,他的一次攻擊最多能使 drd 受到多少傷害。

Input

第1行包含2個整數,依次為n,m,表示drd有n扇防禦門,atm的初始攻擊力為0到m之間的整數。接下來n行,依次表示每一扇防禦門。每行包括一個字符串op和一個非負整數t,兩者由一個空格隔開,且op在前,t在後,op表示該防禦門所對應的操作, t表示對應的參數。n<=10^5

Output

一行一個整數,表示atm的一次攻擊最多使 drd 受到多少傷害。

Sample Input

3 10
AND 5
OR 6
XOR 7

Sample Output

1

思路:

  同屆神犇fcw出過這題的。當時不是很會,今天突然想到要做。還忘了怎麽做,冥思苦想之後發現可以用貪心的思路求(其實是FCWww講過),對於32位,分別枚舉是1或0的情況(如果是1要判斷當前是否還小於等於M)看結果盡可能的貪心讓高位等於1,對於1和0都能取得1的情況,當然是要取0啦!這樣未來的可能就更多,NOI簽到題,不多說上代碼啦

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cctype>
using namespace std;
int opt[110000], num[110000];
int n, m;
int ans[40];
bool check(int idx) {
    int x=0;
    for(int i=0;i<=30;i++) {
        x|=(ans[i]<<i);
    }
    x|=(1<<idx);
    return x<=m;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        char s[6];
        int x;
        scanf("%s%d",s ,&x);
        if(s[0]==‘A‘) {
            opt[i] = 1;
            num[i] = x;
        }
        if(s[0]==‘O‘) {
            opt[i] = 2;
            num[i] = x;
        }
        if(s[0]==‘X‘) {
            opt[i] = 3;
            num[i] = x;
        }
    }
    int i;
    for(i=0;(1<<i)<=m;i++);
    i--;
    for(;i>=0;i--) {
        if(check(i)) {
            int now=1<<i;
            for(int j=1;j<=n;j++) {
                if(opt[j]==1) {
                    now&=num[j];
                }
                if(opt[j]==2) {
                    now|=num[j];
                }
                if(opt[j]==3) {
                    now^=num[j];
                }
            }
            now>>=i;
            if(now&1) {
                ans[i]=1;
            }
        }
        int now=0;
        for(int j=1;j<=n;j++) {
            if(opt[j]==1) {
                now&=num[j];
            }
            if(opt[j]==2) {
                now|=num[j];
            }
            if(opt[j]==3) {
                now^=num[j];
            }
        }
        now>>=i;
        if(now&1) {
            ans[i]=0;
        }
    }
    int x=0;
    for(int i=0;i<=30;i++) {
        x|=(ans[i]<<i);
    }
    int now=x;
    for(int j=1;j<=n;j++) {

        if(opt[j]==1) {
            now&=num[j];
        }
        if(opt[j]==2) {
            now|=num[j];
        }
        if(opt[j]==3) {
            now^=num[j];
        }
    }
    printf("%d\n",now);
}

歡迎來原博客看看 >原文鏈接<

BZOJ 3668: [Noi2014]起床困難綜合癥