带撤销贪心——cf1148F好题
自己不会做,看了题解懂得
从最高位依次往低位遍历,因为偶数个1是不改变符号的,所以带个贪心即可(可以看成是带撤销的。。)
每轮循环用sum记录该位选择1可以减少的值
如果是负数,就不要改成1
如果是正,就改成1,然后增加一次改成1的影响
怎么增加影响:如果一个数的i位改成1,等价于其在最终减少的值 *-1,
比如说原来是a[i],现在和&s 是 一个1,那么就直接变成-a[i]
然后又多了一个1, 那么又变成了 a[i], 即等价于每次影响乘以了 -1
#include <bits/stdc++.h> #define LL long long using namespace std; const int maxn = 300010; LL a[maxn], b[maxn]; int main() { int n; LL sum = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%lld%lld", &a[i], &b[i]); sum += a[i]; } if(sum < 0) { for (int i = 1; i <= n; i++) a[i] = -a[i]; } LL ans = 0; for (int j = 61; j >= 0; j--) { LL s = 0; for (int i = 1; i <= n; i++) { if(b[i] == (1ll << j)) s += a[i]; } if(s > 0) ans |= (1ll << j); for (int i = 1; i <= n; i++) { if((b[i] >> j) & 1) { b[i] ^= (1ll << j); if(s > 0) a[i] = -a[i]; } } } printf("%lld\n", ans); }