dp[i]
的含义具体是什么,其中特别需要注意循环的区间。#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main()
{
int n, q;
cin >> n >> q;
vector<ll> arr(n + 1), dp(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> arr[i];
dp[i] = dp[i - 1] + arr[i];
}
int l, r;
while (q--)
{
cin >> l >> r;
cout << dp[r] - dp[l - 1] << endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main()
{
int n, m, q,x1, x2, y1, y2;
cin >> n >> m >> q;
vector<vector<ll>> arr(n + 1, vector<ll>(m + 1)), dp(n + 1, vector<ll>(m + 1));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
cin >> arr[i][j];
dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + arr[i][j];
}
ll tmp = 0;
while (q--)
{
cin >> x1 >> y1 >> x2 >> y2;
tmp = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1];
cout << tmp << endl;
}
return 0;
}
dp[i] = dp[i - 1] + arr[i]
,要根据具体题目具体分析。本题中的 dp[i]
表示的是 i 位置之前的前缀和,不包括 i 位置,所以 dp 表要多开一个位置,而且还要注意循环的区间。
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n + 1);
for (int i = 1; i <= n; i++)
dp[i] = dp[i - 1] + nums[i - 1];
for (int i = 0; i < n; i++)
{
if (dp[i] == (dp[n] - dp[i + 1]))
return i;
}
return -1;
}
};
其中 f[i]
和 b[i]
分别表示 i 位置之前、之后所有元素之积。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> ret(n), f(n, 1), b(n, 1);
for (int i = 1; i < n; i++)
f[i] = f[i - 1] * nums[i - 1];
for (int i = n - 2; i >= 0; i--)
b[i] = b[i + 1] * nums[i + 1];
for (int i = 0; i < n; i++)
ret[i] = f[i] * b[i];
return ret;
}
};
从前向后统计数组的前缀和,假设以 i 位置为结尾的子数组有 n 个和为 k,则在 i 位置之前的前缀和中有 n 个和为 sum - k 的前缀和,而我们可以在计算前缀和的过程中在哈希表中记录各前缀和出现的次数。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> hash; // 前缀和及其出现的次数
hash[0] = 1; // 表示整个数组的前缀和为k
int sum = 0, ret = 0;
for (int e : nums)
{
sum += e; // 前缀和
if (hash.count(sum - k)) ret += hash[sum - k];
hash[sum]++;
}
return ret;
}
};
这道题和上道题类似,但是这道题主要考下面两个知识点。
假设以 i 位置为结尾的子数组中有 n 个子数组之和能被 k 整除,有 n 个这样的子数组,也就对应着有 n 个上面的 x 区间。根据同余定理我们只需要求 i 位置前面的所有前缀和中有多少个前缀和的余数等于 sum % k
。
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k) {
unordered_map<int, int> hash; // 前缀和的余数及其次数
hash[0] = 1;
int sum = 0, ret = 0;
for (int e : nums)
{
sum += e;
int t = (sum % k + k) % k;
if (hash.count(t)) ret += hash[t];
hash[t]++;
}
return ret;
}
};
本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~