《编程珠玑》代码之路13:数组如何在线性时间内实现多次区间修改

给一个数组,每次对某个区间增加某个值,如何在线性时间内完成。

比如一个数组,刚开始都是0吧,如下表,第一行是下标:

0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0

操作 1 3 5,代表给下标1-3的元素都加5,有很多次这样的操作。

正常来说,这个算法复杂度为n^2。

要实现线性时间,就只能通过某种记录方式,然后再通过记录,还原出最后的数据。

我们开辟一个csum数组,对每一波操作(left, right, value)有:

csum[left -1] -= value;

csum[right] += value;

然后对每一对三元操作都以同样的方式记录。

例如1 3 5操作完成后,csum数组为:

0 1 2 3 4 5 6 7
-5 0 0 5 0 0 0 0

最后按照如下方式还原:

x[i] = x[i + 1] + csum[i];

0 1 2 3 4 5 6 7
0 5 5 5 0 0 0 0

就得到了区间修改后的数组。

完整代码如下:

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

vector<int> nums, csum;
const int NUMS = 10;
const int NINTERVAL = 3;
int main(){

	freopen("in.txt", "r", stdin);
	int value = 4;

	for (int i = 0; i < NUMS + 1; ++i){
		nums.push_back(0);
		csum.push_back(0);
	}
	
	int leftV[NINTERVAL] = {2, 3, 7};
	int rightV[NINTERVAL] = {4, 6, 9};

	for (int i = 0; i < NINTERVAL; ++i){
		if (leftV[i] - 1 >= 0){
			csum[leftV[i] - 1] -= value;
		}

		csum[rightV[i]] += value;
	}

	for (int i = NUMS - 1; i >= 0; --i){
		nums[i] = nums[i + 1] + csum[i];
	}

	for (int i = 0; i < NUMS; ++i){
		cout << nums[i] << endl;
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/beijixiong5622/article/details/84557178