C++ | 基础算法—前缀和和差分

文章介绍了在编程竞赛中如何利用前缀和和差分数组技术优化问题求解,包括构造数组、处理负数边界条件以及避免整数溢出,以降低时间复杂度并提高解题效率。
摘要由CSDN通过智能技术生成

这类题的一般解法思路:

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;
}

       

  • 27
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值