維護區間資訊的資料結構有很多,像線段樹、樹狀陣列等;然而線段樹之類的資料結構往往要寫上一段板子(儘管不是太長),但在演算法競賽中卻很有可能導致我們與別人慢上那麼幾分鐘,所以我們需要準備一種更簡單實用的資料結構,字首和、差分標記就是這樣的資料結構。
我們每次對乙個區間進行加或者減,最後我們求一下每個點的值
差分標記其實與字首和有著密切的關係,我們開始時有乙個初始化為0的sum陣列,每次我們輸入乙個區間a, b和要增加的值d,我們使得sum[a] + d, sum[b] - d,最後我們設乙個變數res為0,for 迴圈遍歷sum陣列每次使res加上sum[i],得到的結果就是這個結點經過修改後最終得到的值
例題1、color the ball
題目描述:n個氣球排成一排,從左到右依次編號為1,2,3....n.每次給定2個整數a b(a <= b),lele便為騎上他的「小飛鴿"牌電動車從氣球a開始到氣球b依次給每個氣球塗一次顏色。但是n次以後lele已經忘記了第i個氣球已經塗過幾次顏色了,你能幫他算出每個氣球被塗過幾次顏色嗎?
分析:差分標記的板子題
參考**
#include #include #include using namespace std;
#define n 110000
int sum[n];
int main()
int res = 0;
for (int i = 1; i < n; ++i)
res += sum[n];
printf("%d\n", res);
}return 0;
}
例題2、區間
題目描述:
有乙個n個元素的陣列a,而他要對a[l]-a[r]進行m次操作:
操作一:將a[l]-a[r]內的元素都加上p
操作二:將a[l]-a[r]內的元素都減去p
最後詢問a[l]-a[r]內的元素之和
分析:這個題涉及到了區間資訊的修改,很容易讓人想到線段樹或者樹狀陣列這類能夠動態的維護區間資訊的資料結構,實際上這只是乙個誤導。如果我們認真讀題的話我們會發現我們僅僅需要查詢一次(加粗體的部分),這時採用bit或者線段樹這種難寫(相比於字首和)的資料結構顯然是不合適的。一種簡單的方法是用差分標記記錄哪些區間進行了修改,然後直接用for迴圈掃一遍就可以了。
#include #include #define n 1100000
typedef long long ll;
int a[n], b[n];
int main()
memset(b, 0, sizeof(b));
while (m--)
else
}ll res = 0, tmp = 0;
int l, r; scanf("%d%d", &l, &r);
for (int i = 1; i <= n; ++i)
printf("%lld\n", res);
}return 0;
}
演算法筆記 差分標記
演算法筆記 所有元素初始值為0才能這麼做。l r全加1 a l a r 1 求一遍字首和為元素本身。求兩遍字首和為元素字首和。例題1 例題2 例題3 l r從1加到r l 1 a l a r 1 r l 2 a r 2 r l 1 求兩遍字首和為元素本身。求三遍字首和為元素字首和。因為更新時複雜度是...
差分約束講解
by ysy 因為差分約束是基於 spfa 的一種解不等式,或等式組的技巧,所以差分約束的前置知識就是 spfa 和對不等式的簡單小變換。因為差分約束只是乙個技巧,所以在這裡我先講解技巧,之後再講解例題。建圖技巧 我們將不等式組分為兩種 a le b val 以及 a ge b val 現在討論第一...
差分詳細講解筆記
那麼我們先來細細地講一下差分到底是個什麼東西吧 首先,差分其實和我們所熟悉的字首和大有相似之處 字首與差分其實是一對 互逆序列 只是換成了b i a i a i 1 那麼我們先來舉乙個例子看看 假如a陣列wei 7 5 2 9 11 19 14 那麼差分數列b就為 7 2 3 7 2 7 5 差分數...