题意: 简单来说就是给出n个固定的操作,每种操作给定一个op和一个正整数x, op是xor, or, and中的一种, 选取 [0~m] 范围内的某个数使其按顺序运算完成后的结果最大。数据范围2<= n <= 1e5, 2 <= m <= 1e9, 0<=x<= 1e9。
分析: 位运算的特点是没有进位,也就是说每位的数是0是1只与运算时x该位的数有关。想要求出最大的ans,可以贪心的使高位尽可能为1。因此从高到低枚举每位是否可以填1,同时注意初值不能大于m。
代码:
#include<bits/stdc++.h>
#define map unordered_map
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
typedef pair<int, int> PII;
typedef pair<string, int> PSI;
int n, m;
vector<PSI> v;
int get(int w, int bit){
for(int i = 0; i < n; i ++){
auto [s, k] = v[i];
if(s == "OR") w |= ((k >> bit) & 1);
else if(s == "AND") w &= ((k >> bit) & 1);
else w ^= ((k >> bit) & 1);
}
return w;
}
void solve(){
cin>>n>>m;
for(int i = 0; i < n; i ++){
string s;
int t;
cin>>s>>t;
v.push_back({s, t});
}
ll ans = 0;
ll val = 0;
for(int i = 29; i >= 0; i --){
ll res1 = get(1, i);
ll res2 = get(0, i);
if(val + (1 << i) <= m && res1 > res2) ans = ans + (res1 << i), val += (1 << i);
else ans = ans + (res2 << i);
}
cout<<ans;
}
int main(){
cin.tie(0) -> sync_with_stdio(false);
//int t; cin>>t; while(t --)
solve();
}