还原差值数组、修改区间中元素_解法

【题解提供者】吴立强

(差值还原数组)解法

思路

根据定义有: A 1 = B 1 , A i = A i − 1 + B i A_1 = B_1, A_i = A_{i-1}+B_i A1=B1,Ai=Ai1+Bi

仔细观察上式可以得到新式: A i = ∑ j = 1 i B j A_i = \sum_{j=1}^i B_j Ai=j=1iBj,即每个元素都是一个前缀的和。

代码展示

#include <iostream>
using namespace std;
typedef long long ll;

int main() {
  int n;  cin >> n;
  int sum = 0, x;
  while(n --) {
  	cin >> x;
  	sum += x;
  	cout << sum << ' ';
  }
  return 0;
}

(修改区间中元素)解法

思路

可以直接修改每个指定区间,不过在加强版题目中会 TLE。

注意到,当对一个数组求前缀和时,数组中每个元素值都会加给一个后缀中的所有元素。

例子:
    原数组   ---前缀和-->   前缀数组
[0,0,0,0,0]            [0,0,0,0,0]
[0,W,0,0,0]            [0,W,W,W,W]
[0,0,0,-W,0]           [0,0,0,-W,-W]
[0,W,0,-W,0]           [0,W,W,0,0]

所以只需要建立一个记录差值的数组,每次区间操作只需要给差值数组修改对应的两个点,其体现在前缀和中就是一个区间的变化。

代码展示

#include <iostream>
using namespace std;
typedef long long ll;

const int N = 100009;
int a[N];
ll c[N];  /// 差值数组

int main() {
  int n;  cin >> n;
  for(int i = 1; i <= n; i ++) cin >> a[i];
  int m;  cin >> m;
  while(m --) {
    int l, r, w;  cin >> l >> r >> w;
    c[l] += w, c[r + 1] -= w;  /// 等价于给区间 [l,r] 都增加了 w
  }
  ll sum = 0;
  for(int i = 1; i <= n; i ++) {
    sum += c[i];  /// 计算前缀和
    cout << a[i] + sum << ' ';  /// 前缀和即是所有操作对原数组的影响
  }
  return 0;
}

算法分析

程序时间复杂度为 O ( n + m ) O(n+m) O(n+m),可以通过 1 0 5 10^5 105 的数据。

算法拓展

上述算法为【差分】算法,其可以将区间修改从区间长度优化至两次单点标记(差分标记)和一次前缀和统计。

其实一个完整数组可以转变为差分数组,而转化方式即为【差值还原数组】一题中 A 数组转化为 B 数组的方式,那么代码可以如下写:

#include <iostream>
using namespace std;
typedef long long ll;

const int N = 200009;
ll c[N];

int main() {
  int n;  cin >> n;
  for(int i = 1; i <= n; i ++) cin >> c[i];
  for(int i = n; i >= 1; i --) c[i] -= c[i - 1];
  int m;  cin >> m;
  while(m --) {
    int l, r, w;  cin >> l >> r >> w;
    c[l] += w, c[r + 1] -= w;
  }
  for(int i = 1; i <= n; i ++) {
    c[i] += c[i - 1];
    cout << c[i] << ' ';
  }
  return 0;
}
  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值