Yurchiu's Blog

P2114 [NOI2014] 起床困难综合症

Yurchiu 2020-11-24, 22:31:43 596 隐藏左右两栏 展示左右两栏

题解 P2114 [NOI2014]起床困难综合症

题意简述

给定 nn 个操作 (opi,ti)(op_i,t_i),其中 opi{and,or,xor}op_i \in \{and,or,xor\} ,即三种位运算之一;tit_i 为非负整数。例:aa 一次操作后变为 aa opiop_i tit_i

f(x)f(x) 表示 xx 依次执行 nn 个操作后的结果。求:max{f(x)x[0,m]}\max\{f(x)\mid x\in [0,m]\}

思路

位运算具有一定的性质,二进制位之间不相互影响。假设一个数的二进制的第 xx 位是 11 ,经过一系列位运算之后得到的数的二进制第 xx 位是 00 ,那么只要一个二进制第 xx 位是 11 的数,经过相同顺序的位运算,其得到的数的二进制的第 xx 位也一定是 00

由于二进制的每一位只有 0011 两种可能性,我们可以预处理出每一位置都是 00 或者都是 11 所得到的结果( 即 f(0)f(0)f(2147483647)f(2147483647) ),预处理之后使用下面的贪心思路:

能用 0011 就一定换;能用 1111 也换,换后若初始攻击力大于 mm,别换就好了。

代码

#include<bits/stdc++.h>
using namespace std;
namespace _yz
{
	const int MAXN=100000+5;
	const int _and=1,_or=2,_xor=3;
	struct Doors{int opt,num;}door[MAXN];
	int n,m,bit0=0,bit1=2147483647,ans=0;
	int calc(int ans,int opt,int num)
	{
		if(opt==_and) ans&=num;
		else if(opt==_or) ans|=num;
		else ans^=num;
		return ans;
	}
	void yzmain()
	{
		string tmp;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			cin>>tmp>>door[i].num;
			if(tmp=="AND") door[i].opt=_and;
			else if(tmp=="OR")  door[i].opt=_or;
			else door[i].opt=_xor;
		}
		for(int i=1;i<=n;i++)
		{
			bit0=calc(bit0,door[i].opt,door[i].num);
			bit1=calc(bit1,door[i].opt,door[i].num);
		}
		for(int i=31;i>=0;i--)//枚举每位,倒序枚举
		{
			if(bit0&(1<<i)) ans+=(1<<i); //能用0换1就一定换;
			else if((bit1&(1<<i))/*能用1换1也换*/&&(m>=(1<<i))/*但要保证初始攻击力不大于 m*/) ans+=(1<<i),m-=(1<<i);
		}
		printf("%d\n",ans);
		return;
	}
}
int main()
{
	//freopen("P2114_2.in","r",stdin);
	//freopen("out.txt","w",stdout);
	_yz::yzmain();
	return 0;
}




本文作者:Yurchiu

本文链接:https://yz-hs.github.io/660034424a48/

版权声明:本博客中所有原创文章除特别声明外,均允许规范转载,转载请注明出处。所有非原创文章,按照原作者要求转载。


By Yurchiu.
其他物件杂物收纳
Hitokoto

Yurchiu 说,除了她以外的人都很强!嘤嘤嘤~~
博客信息
文章数目
158
最近更新
08-21
本站字数
350.6k
文章目录