uoj #2 【NOI2014】起床困难综合症 贪心+位运算

时间:2023-03-09 08:57:08
uoj #2  【NOI2014】起床困难综合症  贪心+位运算

题目链接

给出n个数, 每个数有特定的一种操作, &|^三种, 给出一个m, 初始值属于[0,m],选定一个初始值, 使所有操作做完之后的值最大, 输出这个最大值。

1, 从最高位贪心, 如果初始这一位为0的时候, 所有操作进行完之后结果为1, 那么这一位就已经确定位0。

2, 初始为0, 如果所有操作进行完之后这一位为0, 那么就试初始为1的条件。 设当前位是第pos位, 如果之前已经有的数加上(1<<pos)小于m, 那么这一位为1就是可以的。 当初始为1的时候, 所有操作进行完之后, 如果为1, 那么就将这一位确定为1, 否则这一位为0。

具体看代码。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
int m, ans, n, digit[][];
char c[][];
void cal(int num, int flag) {
int x = ;
for(int i = ; i<n; i++) {
if(c[i][] == 'A') {
x &= digit[i][num];
} else if(c[i][] == 'O') {
x |= digit[i][num];
} else {
x ^= digit[i][num];
}
}
if(x) {
ans += (<<num);
return ;
}
if(flag) {
x = ;
for(int i = ; i<n; i++) {
if(c[i][] == 'A') {
x &= digit[i][num];
} else if(c[i][] == 'O') {
x |= digit[i][num];
} else {
x ^= digit[i][num];
}
}
if(x == ) {
ans += (<<num);
m -= (<<num);
}
}
}
int main()
{
int x;
cin>>n>>m;
for(int i = ; i<n; i++) {
scanf("%s%d", c[i], &x);
int num = ;
while(x) {
digit[i][num++] = x&;
x>>=;
}
}
for(int i = ; i>=; i--) {
int flag = ;
if((<<i)<=m)
flag = ;
cal(i, flag);
}
cout<<ans<<endl;
return ;
}