前缀和
1)求和
https://www.luogu.com.cn/discuss?forum=P8772
2)统计子矩阵
https://www.luogu.com.cn/problem/P8783
前缀和,四层循环tle2
#include <iostream>
using namespace std;
const int MAXN = 510;
int a[MAXN][MAXN];
int s[MAXN][MAXN]; // 前缀和矩阵
int main() {
int n, m, k;
cin >> n >> m >> k;
// 输入矩阵元素
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
// 计算前缀和矩阵
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
}
}
int count = 0;
// 枚举左上角坐标 (x1, y1)
for (int x1 = 1; x1 <= n; x1++) {
for (int y1 = 1; y1 <= m; y1++) {
// 枚举右下角坐标 (x2, y2)
for (int x2 = x1; x2 <= n; x2++) {
for (int y2 = y1; y2 <= m; y2++) {
// 利用前缀和矩阵计算子矩阵的和
int sum = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
// 判断子矩阵的和是否不超过 K
if (sum <= k) {
count++;
}
else {
break;
}
}
}
}
}
cout << count << endl;
return 0;
}
正解
#include<bits/stdc++.h>
using namespace std;
long long n, m, k, a[510][510], sum[510][510], b[510];
long long l, r, now, ans;
int main() {
cin >> n >> m >> k;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> a[i][j];
for (int j = 1;j <= m;j++)
for (int i = 1;i <= n;i++)
sum[i][j] = sum[i - 1][j] + a[i][j];
//处理竖着的和 第j列前i个数的和
for (int x = 1;x <= n;x++)
for (int y = x;y <= n;y++) {
// cout<<x<<" "<<y<<":"<<endl;
//横线x y
for (int j = 1;j <= m;j++)
b[j] = sum[y][j] - sum[x - 1][j];
//双指针 这里已经简化到普通的子串和小于k了
l = 1;r = 1;now = 0;
for (r = 1;r <= m;r++) {
now += b[r];
if (now <= k) {
//每次r++新增一个数,这个数可以和前面组成r-l+1,以这个新增的数结尾的子数组
// cout<<l<<" "<<r<<" "<<now<<endl;
ans += r - l + 1;
}
else {
while (now > k) {
now -= b[l];
l++;
}
ans += r - l + 1;
}
}
// cout<<"-------"<<endl;
}
cout << ans << endl;
return 0;
}
3)子串简写数量统计
https://www.lanqiao.cn/problems/3514/learning/
忘记初始化字符串以后的,之后应该初始化为最大的,并且如果数据范围不够大会导致某些测试点,这里开5e5+10会错,6e5+10可以
错误代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 5e5 + 10;
int st1[maxn], st2[maxn];
int k;
string s;
char c1, c2;
int ans;
signed main()
{
cin >> k;
cin >> s;
cin >> c1 >> c2;
for (int i = 0;i < s.size();i++)
{
/* st1[i] = st1[i - 1];
if (s[i] == c1)
st1[i]++;*/
st2[i] = st2[i - 1];
if (s[i] == c2)
st2[i]++;
}
for (int i = 0;i < s.size();i++)
{
if (s[i] == c1)
{
ans += st2[s.size()-1] - st2[i + k-2];
}
}
cout << ans << endl;
}
前缀和
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 6e5 + 10;
int st1[maxn], st2[maxn];
int k;
string s;
char c1, c2;
int ans;
signed main()
{
cin >> k;
cin >> s;
cin >> c1 >> c2;
for (int i = 0;i < s.size();i++)
{
/* st1[i] = st1[i - 1];
if (s[i] == c1)
st1[i]++;*/
st2[i] = st2[i - 1];
if (s[i] == c2)
st2[i]++;
}
for (int i = s.size();i < maxn;i++) st2[i] = st2[s.size() - 1];
for (int i = 0;i < s.size();i++)
{
if (s[i] == c1)
{
ans += st2[s.size() - 1] - st2[i + k - 2];
}
}
cout << ans << endl;
}
浙公网安备 33010602011771号