CF1148F - Foo Fighters
题意:你有n个物品,每个都有val和mask。
你要选择一个数s,如果一个物品的mask & s含有奇数个1,就把val变成-val。
求一个s使得val总和变号。
解:分步来做。发现那个奇数个1可以变成:每一个1就变一次。
然后把这些物品按照最高位1来分类。从0到61考虑每一类。
我们试图使每一类都与sum异号,这样总和也异号了。
具体来说就是看看这一类的总和,如果同号就把这以一位变成1。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 300010; 5 6 struct Node { 7 LL mask, val; 8 int id, cnt; 9 inline bool operator < (const Node &w) { 10 return mask < w.mask; 11 } 12 }node[N]; 13 14 int main() { 15 16 int n; 17 LL sum = 0; 18 scanf("%d", &n); 19 for(int i = 1; i <= n; i++) { 20 scanf("%lld%lld", &node[i].val, &node[i].mask); 21 sum += node[i].val; 22 for(int j = 0; j <= 61; j++) { 23 if((node[i].mask >> j) & 1) { 24 node[i].id = j; 25 } 26 } 27 } 28 if(sum < 0) { 29 for(int i = 1; i <= n; i++) { 30 node[i].val *= -1; 31 } 32 } 33 LL ans = 0; 34 for(int i = 0; i <= 61; i++) { 35 LL t = 0; 36 for(int j = 1; j <= n; j++) { 37 if(node[j].id != i) { 38 continue; 39 } 40 t += node[j].val; 41 } 42 if(t > 0) { 43 ans |= (1ll << i); 44 for(int j = 1; j <= n; j++) { 45 if((node[j].mask >> i) & 1) { 46 node[j].val *= -1; 47 } 48 } 49 } 50 } 51 printf("%lld\n", ans); 52 return 0; 53 }