牛客-练习赛101-C-推理小丑
当时自己的贪心错了, 难受 C都没做出来
思路:
因为整个序列都是严格递增的, 所以每个数都或上 2^(31 - 1)(11111…) 肯定是严格递增的。
那么就从高位往低位贪心,先设第i位为0,从 i -1 ~ 0位考虑(从高位到低位) 如果存在一个数x使得严格递增,那么第i位为1的贡献就为0,所以让第i位为0, 否则第i位为1。
还需要考虑在 i-1 ~ 0的考虑中。
如果让第j位为1,导致整个序列不满足递增(非单调),那么就算剩余的位全为1,也不会让非递增边成递增 因为 2^i > 2 ^ i - 1, 所以当前情况必须要让第i位为1。
但是需要考虑相等情况, 此时应该继续往后搜索,因为可能会存在相等情况,变为递增情况,在i-1 ~ 0位考虑完后, 如果满足严格递增就说明那么第i位为1的贡献就为0,所以让第i位为0, 否则第i位为1。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int s[N];
int a[32];
int main(){
int n;
cin >> n;
for(int i = 0; i < n; ++ i) cin >> s[i];
int x = 0;
for(int i = 30; i >= 0; -- i){
int now = x;
bool flag;
for(int j = i - 1; j >= 0; -- j){
now |= 1 << j;
flag = true;
for(int k = 1; k < n; ++ k)
if((s[k] & now) < (s[k - 1] & now)){
flag = false;
break;
}
if(!flag) now ^= 1 << j;
}
flag = true;
for(int k = 1; k < n; ++ k){
if((s[k] & now) <= (s[k - 1] & now)){
flag = false;
break;
}
}
//cout << i << " " << now << " " << flag << endl;
if(!flag) x |= 1 << i;
}
cout << x << endl;
return 0;
}