CH - 0104 起床困难综合症(位运算+贪心)
題目鏈接:點(diǎn)擊查看
題目大意:我們需要構(gòu)造一個(gè)初始值start,范圍在[0,m],要求使用這個(gè)初始值進(jìn)行k次操作后得到的答案最大,每次操作分為三個(gè)類型:
現(xiàn)在我們需要構(gòu)造出這個(gè)start,使得經(jīng)過k次操作后得到的end最大,輸出end
題目分析:首先我們肯定不能直接枚舉m,然后維護(hù)最大值,因?yàn)閙給到了1e9,單單只是枚舉一個(gè)m都會(huì)超時(shí),就別再提每個(gè)m還需要n次操作,暴力的時(shí)間復(fù)雜度是n*m,都到了1e14,完全不用考慮了
我們需要知道關(guān)于位運(yùn)算的一個(gè)主要特點(diǎn):在二進(jìn)制表示下不進(jìn)位
換句話說,每一個(gè)數(shù)字的二進(jìn)制都是相互獨(dú)立的,所以我們可以按位討論,這樣就能在logn的時(shí)間復(fù)雜度內(nèi)枚舉完m符合情況的狀態(tài)了,時(shí)間復(fù)雜度下降為n*logm,最多3e6
現(xiàn)在我們需要討論一下該怎么按位計(jì)算,如果這個(gè)題目沒有m的約束,那么我們按位從小到大枚舉和從大到小枚舉都是可以的,但是加了這個(gè)約束之后,我們就只能按位從大到小枚舉才能獲得最優(yōu)解了,因?yàn)槿绻覀儚男〉酱竺杜e的話,枚舉了其中一個(gè)比較小的位置,雖然對(duì)答案有貢獻(xiàn),但卻占據(jù)了小于等于m的這個(gè)空間,若后續(xù)還有更大的位置可以做出貢獻(xiàn),卻被m這個(gè)約束卡出去的話,那么此時(shí)答案必定不是最優(yōu)的
再就是討論一下某個(gè)位置該放0或1的情況,因?yàn)槲覀円澬淖宔nd盡可能的大,所以對(duì)于某一位置,我們計(jì)算一下res1和res0,res1和res0分別是在當(dāng)前位置放1和放0情況下返回的答案,我們肯定會(huì)讓end加上兩者中較大的一個(gè),如果兩者相等的話優(yōu)先放0,不過別忘了還有m這個(gè)約束,因?yàn)樵诜?放1對(duì)答案的貢獻(xiàn)相同的情況下,放1會(huì)占據(jù)m的空間,所以放0才是最優(yōu)解,總結(jié)下來在某一位放1還是放0可以分為兩種情況:start+res1<=m&&res1>res0滿足時(shí)放1,否則放0
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int n,m;struct Node {char op[5];int val; }op[N];int cal(int bit,int x)//計(jì)算當(dāng)前bit位,初始值為x的情況下得到的答案 {for(int i=1;i<=n;i++){int temp=op[i].val>>bit&1;if(op[i].op[0]=='A')x&=temp;else if(op[i].op[0]=='O')x|=temp;elsex^=temp;}return x<<bit; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%s%d",op[i].op,&op[i].val);int start=0,end=0;//start:初始攻擊力 end:最終攻擊力 for(int i=30;i>=0;i--)//枚舉每一位,注意要從最高位開始枚舉才能達(dá)到最優(yōu)解 {int res1=cal(i,1);//當(dāng)前第i位為1的情況下運(yùn)算后得到的結(jié)果 int res0=cal(i,0);//當(dāng)前第i位為0的情況下運(yùn)算后得到的結(jié)果 if(start+res1<=m&&res1>res0)//滿足條件,第i位用res1填充{start+=res1;//實(shí)時(shí)更新start end+=res1;}else//否則用res0填充 end+=res0;}printf("%d\n",end);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的CH - 0104 起床困难综合症(位运算+贪心)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 2586 How far a
- 下一篇: (转)快速统计二进制中1的个数