这类题的一般解法思路:
1. 先要根据题意输入一个数组。
2. 根据题意构造一个前缀和数组(或差分数组)
3. 对数组进行操作
4. 如果是差分数组可以前缀和还原
5. 最后输出答案
前缀和是一种预处理的方法,当询问的次数较多时,每一次如果都用暴力解决就可能出现超时,所以用前缀和提前求出一些数的和,降低了时间复杂度。
下面是我做到的几道相关的题 :
这道题的解题思路很巧妙,因为k的取值范围比较小采用二维数组,一维用来记录输入的数据,一维用来表示他是几次方的。 我遇到的一个小问题是数组a[6][N], prefix[6][N]数组第一次开成int后开小了,改成long long就没问题了。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll p = 1e9 + 7;
const ll N = 1e5 + 9;
ll a[6][N], prefix[6][N];
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i ++)
cin >> a[1][i];
for (int i = 2; i <= 5; i++)
for (int j = 1; j <= n; j++)
a[i][j] = a[i - 1][j] * a[1][j] % p;
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= n; j++)
prefix[i][j] = (prefix[i][j - 1] + a[i][j]) % p;
while (m--) {
int l, r, k;
cin >> l >> r >> k;
cout << (prefix[k][r] - prefix[k][l - 1] + p) % p << '\n';
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
int a[N], diff[N];
void solve(int n, int m) {
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
diff[i] = a[i] - a[i - 1];
}
int x, y, z;
while(m --) {
cin >> x >> y >> z;
diff[x] += z;
diff[y + 1] -= z;
}
//前缀和还原
for (int i = 1; i <= n; i++) {
a[i] = a[i - 1] + diff[i];
}
for (int i = 1; i <= n;i++) {
cout << a[i] <<' ';
}
cout << endl;
}
int main()
{
int n, m;
while(cin >> n >> m) solve(n, m);
return 0;
}
这道题我遇到的主要问题在于,题目要求如果答案是负数则输出零,其实就是max(0, a[i]),取其中大的数就可以了,但是要注意的是数组为防止不够,开的long long数组,与long long相比较的零也要是ll类型的零,max(0ll, a[i]);
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 +9;
ll a[N], d[N];
int main() {
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
d[i] = a[i] - a[i - 1];
}
while(q --) {
int l, r, x;
cin >> l >> r >> x;
d[l] += x;
d[r + 1] -= x;
}
for (int i = 1; i <= n; i++) {
a[i] = a[i - 1] + d[i];
}
for (int i = 1; i <= n; i++) {
cout << max(0ll, a[i]) << ' ';
}
return 0;
}