0%

2871. 将数组分割成最多数目的子数组

2871.将数组分割成最多数目的子数组

题目描述:

给你一个只包含 非负 整数的数组 nums

我们定义满足 l <= r 的子数组 nums[l..r] 的分数为 nums[l] AND nums[l + 1] AND ... AND nums[r] ,其中 AND 是按位与运算。

请你将数组分割成一个或者更多子数组,满足:

  • 每个 元素都 属于一个子数组。
  • 子数组分数之和尽可能

请你在满足以上要求的条件下,返回 最多 可以得到多少个子数组。

一个 子数组 是一个数组中一段连续的元素。

数据范围:

$1\le nums.len \le 10^5;0\le nums[i] \le 10^6$

题解:

首先看全是与运算,与运算之后出现小于等于自己的结果。假设有两段, $x,y$ 。则因为 $x\and y \le min(x,y)$ 。因此只能 $x=y$ 。并且因为 $x + x = 2\times x = x$ 可以得到 $x = 0$ 。每一段的和只能为 $0$ 。

因此只用贪心的分成最多段的 $0$ 即可。

代码:

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
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 int INF = 0x3f3f3f3f;
int maxSubarrays(vector<int> &nums)
{
int sum = nums[0];
int n = nums.size();
for (int i = 1; i < n; ++i)
{
sum &= nums[i];
}
if (sum != 0)
return 1;
int curSum = (1 << 20) - 1;
int cnt = 0;
for (int i = 0; i < n; ++i)
{
curSum &= nums[i];
if (curSum == 0)
{
cnt++;
if (i == n - 1)
break;
curSum = (1 << 20) - 1;
}
}
return cnt;
}
};