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