📅  最后修改于: 2023-12-03 15:19:37.483000             🧑  作者: Mango
给定一个数组和多个查询,每个查询包含一个范围 [L, R]。您需要回答在子数组 [L, R] 中有多少元素是 2 的幂次方。
示例 1:
输入:
arr = [1, 2, 3, 4, 5],
queries = [[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [2, 4], [2, 5], [2, 2], [2, 3], [3, 3], [3, 4], [3, 5], [4, 4], [4, 5], [5, 5]]
输出:
[0, 1, 1, 2, 2, 1, 1, 1, 1, 0, 1, 1, 1, 2, 1]
我们可以使用前缀和来解决这个问题。
我们可以使用一个二维数组 dp,其中 dp[i][j] 表示在数组中从 i 开始的连续的 2 的幂的个数,在范围 [i, j] 中的 2 的幂次方元素计数可以通过以下方式得到:
count = dp[j][j] - dp[i-1][j]
这里是标准前缀和的应用。
初始化 dp[0][i] 的值为 arr[i] 是否是 2 的幂次方,如果是,则 dp[0][i] = 1,否则为 0。
接下来,我们进行以下迭代:
dp[k][i] 的值为 dp[k-1][i] + dp[k-1][i+1],如果 i + 1 到 2^(k-1)-1 中的所有元素都是 2 的幂次方,那么 dp[k][i] 也是 2 的幂次方。
接下来,当我们计算查询时,我们可以通过以下公式计算在闭区间 [L, R] 中 2 的幂次方元素计数:
count = dp[log2(R-L+1)][L] - dp[log2(R-L+1)][R]
我们首先需要 O(N logN) 的时间来计算 dp 数组。之后每个查询的时间复杂度为 O(1),所以总时间复杂度为 O(N logN + Q)。
vector<int> count2Powers(vector<int>& arr, vector<vector<int>>& queries) {
int n = arr.size();
vector<vector<int> > dp(32, vector<int>(n, 0));
for (int i = 0; i < n; i++) {
dp[0][i] = (arr[i] && ((arr[i] & (arr[i]-1)) == 0));
}
for (int k = 1; k < 32; k++) {
for (int i = 0; i + (1 << k) - 1 < n; i++) {
dp[k][i] = dp[k-1][i] + dp[k-1][i+(1<<(k-1))];
if (dp[k-1][i] == (1 << (k-1))) {
dp[k][i] += dp[k-1][i+(1<<(k-1))];
}
}
}
vector<int> res;
for (const auto& q : queries) {
int L = q[0], R = q[1];
int count = dp[log2(R-L+1)][L];
if (L > 0) {
count -= dp[log2(R-L+1)][L-1];
}
res.push_back(count);
}
return res;
}