题目描述:
给你一个整数数组 nums
和一个整数 k
,请你返回 nums
中有多少个子数组满足:子数组中所有元素按位 AND
的结果为 k
。
数据范围:
$1\le nums.len \le 10^5, 0 \le nums[i],k \le 10^9$
题解:
按照 logtrick 可以快速处理出所有以 $nums[i]$ 为终点的区间位运算和。而且此时 $nums[i]$ 左侧的全是他的子集。因此可以直接找出所有与 $k$ 相等的,这里可以用二分,因为最后得到的数组是升序的。
也可以找出与 $k$ 最接近的,这时就需要使用二分找到 $\ge k$ 的位置,然后使用他和他前面的数字更新最优解。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| auto optimize_cpp_stdio = []() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr); return 0; }(); class Solution { public: const static int maxn = 1e5 + 10; const static int maxm = 1e5 + 10; const static long long mod = 1e9 + 7; const long long INF_LL = 0x3f3f3f3f3f3f3f3f; const int INF = 0x3f3f3f3f; long long countSubarrays(vector<int> &nums, int k) { int n = nums.size(); long long ans = 0; for (int i = 0; i < n; ++i) { if(nums[i] == k) ans++; int j; for (j = i - 1; j >= 0; --j) { if ((nums[j] & nums[i]) == nums[j]) { break; } nums[j] &= nums[i]; } int cnt = upper_bound(nums.begin(), nums.begin() + i, k) - lower_bound(nums.begin(), nums.begin() + i, k); ans += cnt; } return ans; } };
|
找出最接近的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| auto optimize_cpp_stdio = []() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr); return 0; }(); class Solution { public: const static int maxn = 1e5 + 10; const static int maxm = 1e5 + 10; const static long long mod = 1e9 + 7; const long long INF_LL = 0x3f3f3f3f3f3f3f3f; const int INF = 0x3f3f3f3f; int minimumDifference(vector<int> &nums, int k) { int n = nums.size(); int ans = INT_MAX; for (int i = 0; i < n; ++i) { for (int j = i - 1; j >= 0; --j) { if ((nums[j] | nums[i]) == nums[j]) break; nums[j] |= nums[i]; } int l = 0, r = i; int index = -1; while (l <= r) { int mid = (l + r) >> 1; if(nums[mid] >= k) { index = mid; l = mid + 1; }else r = mid - 1; } if(index == -1) { ans = min(ans, abs(nums[0] - k)); } else { ans = min(ans, abs(nums[index] - k)); if(index + 1 <= i) { ans = min(ans, abs(nums[index + 1] - k)); } } } return ans; } };
|