欢迎光临散文网 会员登陆 & 注册

差分思想与实际应用

2022-03-22 14:16 作者:萧云纹  | 我要投稿

欢迎来到萧云纹的编程随笔,本片我们将讨论差分思想。

差分思想

差分思想,一个用于优化频繁大区间修改的思想,具体如下:

设数组val、差分数组differ,val存放初始值,而differ[i]存储的就是val[i]和val[i - 1]的差,所以

     ①differ[i] = val[i] - val[i - 1]

     (当i = 0时differ = 0)

根据①,很容易推出

      ②val[i] = differ[0] + differ[1] + ...... +differ[i];

推理过程:展开②等号右侧,即为

      val[i] = 0 + val[1] - val[1] + val[2] - val[2] + val[3] + ...... + val[i - 1] - val[i - 1] + val[i]

              = val[i](抵消)

此时,如果我们想使得val数组的x~y全部加上k,因为val[x+1]~val[y]中每一位数和它前面的一个数的差不变,只有val[x],val[y+1]和其前面一位的差改变了,所以使val数组的x~y全部加上k这个操作和将differ[x]加上k,differ[y + 1]减去k这个效率更高的操作是等价的。

但是如果我们使用差分思想优化了区间的修改效率,使其变成了一个常数级的操作,但是对val[i]的访问因为需要使用到②式,使其效率变为了O(i),这是差分思想的一个劣势。

不多说了,直接开码!

题目描述

输入一串数,允许对其进行两个操作:
 操作①:输入x、y、k,给val[x]~val[y]间的每一个数字加上k

操作②:输入i,输出val[i]的值 

输入输出格式

输入格式:

第一行输入两个数N、M,以空格隔开,分别代表val数组中数的个数,和总操作的个数。

第二行输入N个数,是val数组每一位的值,下标从1开始,以空格隔开。

下面从第3行到第m+三行,输入命令,命令的格式如下:

操作①:1 x y k。以空格隔开,给val[x]~val[y]间的每一个数字加上k

操作②:2 i。以空格隔开,输出val[i]的值

输出格式:

一共m行,即操作②的结果(操作①没有输出)

输入输出样例

输入样例#1: 

5 5

1 5 4 2 3

1 2 4 2

2 3

1 1 5 -1

1 3 5 7

2 4

输出样例#1: 复制

6

10

 

题目解法:

C++代码,建议先自己思考/写代码再阅读以下部分。

操作①代码:

inline void Operator1(int *arrayPtr)

{

int l, r, v;

scanf("%d%d%d", &l, &r, &v);

arrayPtr[l] += v;

arrayPtr[r + 1] -= v;

}

操作②代码:

inline void Operator2(int *arrayPtr)

{

int index, temp = 0;

scanf("%d", &index);

for(int i = 0; i <= index; i++) {

temp += arrayPtr[i];

}

printf("\n%d\n", temp);

}

总体:

#include<bits/stdc++.h>

using namespace std;

 

inline void Operator1(int *arrayPtr)

{

int l, r, v;

scanf("%d%d%d", &l, &r, &v);

arrayPtr[l] += v;

arrayPtr[r + 1] -= v;

}

 

inline void Operator2(int *arrayPtr)

{

int index, temp = 0;

scanf("%d", &index);

for(int i = 0; i <= index; i++) {

temp += arrayPtr[i];

}

printf("\n%d\n", temp);

}

 

int main()

{

int n, m;

scanf("%d%d", &n, &m);

int val[n + 5], differ[n + 5];

differ[0] = 0;

val[0] = 0;

for(int i = 1; i <= n; i++) {

scanf("%d", &val[i]);

differ[i] = val[i] - val[i - 1];

}

int oper;

while(m--) {

scanf("%d", &oper);

if(oper == 1) {

Operator1(differ);

}

else {

Operator2(differ);

}

}

return 0;

}

这篇随笔到此结束,有什么问题欢迎私信我或者在评论区提出,我们下次再会。


差分思想与实际应用的评论 (共 条)

分享到微博请遵守国家法律