差分標記-HDU1556 Color the ball

差分標記

什麼是差分標記?
差分標記,是一種和前綴和相對的離線算法。
所謂差分就是將數組a每一項與前一項做差,記作差分數組b,易得對數組b做一遍前綴和就得到了原來的a數組。
因爲是離線算法所以修改操作一定要在查詢操作之前,它可以維護多次對序列的一個區間加減上一個數,最後詢問某一位的數。

例題

傳送門: HDU-1556

N個氣球排成一排,從左到右依次編號爲1,2,3…N.每次給定2個整數a b(a <= b),lele便爲騎上他的“小飛鴿"牌電動車從氣球a開始到氣球b依次給每個氣球塗一次顏色。但是N次以後lele已經忘記了第I個氣球已經塗過幾次顏色了,你能幫他算出每個氣球被塗過幾次顏色嗎?

input:

每個測試實例第一行爲一個整數N,(N <= 100000).接下來的N行,每行包括2個整數a b(1 <= a <= b <= N)。
當N = 0,輸入結束。

output:

每個測試實例輸出一行,包括N個整數,第I個數代表第I個氣球總共被塗色的次數。

Sample Input:

3
1 1
2 2
3 3
3
1 1
1 2
1 3
0

Sample Output:

1 1 1
3 2 1

分析

本題原數組a值全爲0,那麼相應差分數組b也初始化0即可。每次修改區間[x,y]值加1,那麼差分數組b更新b[x]++,b[y+1]–即可,最後循環前綴和還原數組a並輸出。

代碼

#include<cstdio>
#include<string.h>
using namespace std;
const int maxn = 100005;
int b[maxn];
int main() {
	int x, y, n;
	while (~scanf("%d", &n) && n) {
		memset(b, 0, sizeof(b));
		for (int i = 0; i < n; i++) {
			scanf("%d%d", &x, &y);
			b[x]++;//更新差分數組b的區間[x,y]
			b[y + 1]--;
		}
		int ans = 0;
		for (int i = 1; i < n; i++) {
			ans += b[i];//前綴和還原數組a
			printf("%d ", ans);
		}
		ans += b[n];
		printf("%d\n", ans);//輸出末尾換行處理
	}
	return 0;
}

小結

  1. 相對於線段樹/數組數組而言,差分代碼簡短易寫能節省大量時間。
  2. 差分標記只適用於離線的區間修改問題,如果是在線(邊改邊查)的話應該用線段樹或樹狀數組等。

你的點贊將會是我最大的動力

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章