Week5--作業--B -- TT's Magic Cat [差分數組]

題目描述

Thanks to everyone’s help last week, TT finally got a cute cat. But what TT didn’t expect is that this is a magic cat.
One day, the magic cat decided to investigate TT’s ability by giving a problem to him. That is select n cities from the world map, and a[i] represents the asset value owned by the i-th city.
Then the magic cat will perform several operations. Each turn is to choose the city in the interval [l,r] and increase their asset value by c. And finally, it is required to give the asset value of each city after q operations.

Could you help TT find the answer?

輸入

The first line contains two integers n,q (1≤n,q≤2⋅105) — the number of cities and operations.
The second line contains elements of the sequence a: integer numbers a1,a2,…,an (−106≤ai≤106).
Then q lines follow, each line represents an operation. The i-th line contains three integers l,r and c (1≤l≤r≤n,−105≤c≤105) for the i-th operation.

輸出

Print n integers a1,a2,…,an one per line, and ai should be equal to the final asset value of the i-th city.

樣例輸入

4 2
-3 6 8 4
4 4 -2
3 3 1

樣例輸出

-3 6 9 2

思路

綜述

這道題主要考察了一個新的方法:差分
針對兩個數組而言,設原數組A和差分數組B數組;範圍:[1,n]
滿足:
1)B[1] = A[1];
2)B[i] = A[i] - A[i-1];
所以有如下性質:
1)B的數組前綴和 == A數組的元素值
SUM{B[1~i]} = A[i]
2)A 數組的區間加 == B數組的單點修改
A[L]~A[R] 均加上c
等於 B[L]+=c B[R+1]-=c;

過程

結構體:
開大數組來存儲每一個矩形。

struct node {
	long long value;
	long long l;//存左側編號
	long long r;//存右側編號
	long long number;//編號
};
node Node[100010];
Step1:輸入

構建兩個數組

	for (long long i = 1; i <= n; i++) {
		cin >> a[i];
	}
	b[1] = a[1];
	for (long long i = 2; i <= n; i++) {
		b[i] = a[i] - a[i - 1];
	}
Step2:操作A數組 => 操作B數組

按照性質進行操作
只有一點需要注意:
當 操作的是A數組的最後一個元素值的時候,不需要操作B[R+1]-=C
此時B數組越界,而且這時只需要B[L]+=c;

	for (long long i = 0; i < q; i++) {
		cin >> L >> R;
		cin >> c;
		b[L] += c;
		if (R != n)
			b[R + 1] -= c;
	}

總結

1、本題中與A題一樣也是要考慮數據範圍的問題,
1)這裏初始化時,最大是106
2)操作的個數是105
3)每次操作的數值最大是105
如果用int可能會精度不夠
int的範圍是-2147483648~2147483647
2、雖然A數組和差分數組有關係
A 數組的區間加 == B數組的單點修改
但是操作A數組區間時,如果操作到A數組的最後一個位置,這時,只需要操作B數組的區間左端點。

代碼

#include <iostream>
#include <stack>
using namespace std;
struct node {
	long long value;
	long long l;
	long long r;
	long long number;
};
node Node[100010];
int main() {
	long long n;
	while (1) {
		cin >> n;
		if (n == 0)break;
		stack<node> S;
		for (long long i = 0; i < n; i++) {
			cin >> Node[i].value;
			Node[i].number = i;
		}
		//確定右端點
		for (long long i = 0; i < n; i++) {
			//如果棧空,直接push
			if (S.empty()) {
				S.push(Node[i]);
			}
			else {
				//如果棧非空,則將棧內每一個比當前元素值小的值都pop
				while (!S.empty() && S.top().value > Node[i].value) {
					//pop出來的同時,對出棧的矩形記錄右端點的值
					Node[S.top().number].r = i;
					S.pop();
				}
				S.push(Node[i]);
			}
		}
		//遍歷完一遍之後,對棧內所有的元素,其右端點都是n
		while (!S.empty()) {
			Node[S.top().number].r = n;
			S.pop();
		}
		//確定左端點
		//與確定右端點類似,只不過方向相反
		for (long long i = n - 1; i >= 0; i--) {
			if (S.empty()) {
				S.push(Node[i]);
			}
			else {
				while (!S.empty() && S.top().value > Node[i].value) {
					Node[S.top().number].l = i;
					S.pop();
				}
				S.push(Node[i]);
			}
		}
		while (!S.empty()) {
			Node[S.top().number].l = -1;
			S.pop();
		}
		long long tot = -10000;
		for (long long i = 0; i < n; i++) {
			if (Node[i].value * (Node[i].r - Node[i].l - 1) > tot)
				tot = Node[i].value * (Node[i].r - Node[i].l - 1);
		}
		cout << tot << endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章