學習筆記 關於差分

2022-05-31 08:54:10 字數 2780 閱讀 9094

本篇參考 【顧z】dalao的講解。

現講一下差分陣列的定義吧。

a[i]=σn

j=1  b[j]。

幾個栗子:

原陣列1,3,5,2,4。

差分陣列1,2,2,-3,2。

那麼這個陣列有什麼優勢呢?

如果我們要在原陣列中修改一段區間的值,假如是給l到r這段區間加上x,那麼它在差分陣列中的體現就是:b[l]+x,b[r+1]-x。

也就是說:我們把區間修改變成了單點修改。

例題:at2442(洛谷上直接搜就好),洛谷p3948,p3943。其中p3943的題解戳這裡。(難度由低到高排序,在這裡再次感謝顧z dalao)

樹上差分這個東西一般被用來解決樹上的路徑計數問題。

那麼當我們要修改7到8這一條鏈上的值,給它每個點加上1,我們應該怎麼做呢?

對於一顆樹(描紅的點是要加的):

cnt[u]表示給根到u結點的路徑經過的所有點都加上cnt[u]。

我們只需要在差分陣列的7號點加1,8號點加1,他們的lca 4號點-1,lca的父親2號點-1,就行了。

為什麼呢?

cnt[7]+1:我們把1,2,4,7四個節點加上了1。

cnt[8]+1:我們把1,2,4,6,8五個節點加上了1。

注意到此時由根(1)到lca的父親(2)的路徑上所有點都多加了兩遍1,而lca被多加了一次,所以:

cnt[4]-1:我們把1,2,4三個點都減了1。

cnt[2]-1:我們把1,2這兩點減了1。

對於查詢,在dfs時把以它為根的子樹中差分陣列的值都累加起來就是它當前的值了(就相當於是把差分陣列搬到樹上了嘛)。

得出,點差分:

cnt[u]++      cnt[v]++      

cnt[lca]--     cnt[father[lca]]--

procedure

getans(u,father:longint);

vari,v:longint;

begin

g[u]:=cnt[u];

i:=head[u];

while i<>0

dobegin

v:=vet[i];

if v<>father then

begin

getans(v,u);

g[u]:=g[u]+g[v];

end;

i:=next[i];

end;  

if g[u]>ans then ans:=g[u];

end;

begin

for i:=1

to m do

begin

read(x,y);

z:=lca(x,y);

inc(cnt[x]); inc(cnt[y]);

dec(cnt[z]); dec(cnt[f[z,

0]]);

end;  getans(1,0); //答案統計再g陣列裡。

end.

類似的,我們要給u到v這一條鏈上所有邊都加1,也是差不多的。

還是那張圖(描紅的邊是要加的):

我們把邊壓到點裡(壓到下面的那個點)。

我們只需要在差分陣列的7號點加1,8號點加1,他們的lca 4號點-2就行了。

為什麼呢?

cnt[7]+1:我們把1到2,2到4,4到7這三條邊都加1。

cnt[8]+1:我們把1到2,2到4,4到6,6到8這四條都加1。

注意到此時根(1)到它們的lca(4)的路徑上所有的邊都被多加了2次,所以:

cnt[4]-2:我們把1到2,2到4這兩條邊都減2。

得出邊差分:

cnt[u]++      cnt[v]++

cnt[lca]-2 

很簡單,不是嗎?

procedure

getans(u,father:longint);

vari,v:longint;

begin

g[u]:=cnt[u];

i:=head[u];

while i<>0

dobegin

v:=vet[i];

if v<>father then

begin

getans(v,u);

g[u]:=g[u]+g[v];

if (g[v]=num)and(dist[i]>=k) then flag:=true;

end;

i:=next[i];

end;end

;begin

for i:=1

to m do

begin

read(u[i],v[i]);

grand[i]:=lca(u[i],v[i]);

len[i]:=d[u[i]]+d[v[i]]-2*d[grand[i]];

if len[i]>max then max:=len[i];

end;

getans(

1,0); //答案存再g陣列裡。

end;

例題:洛谷p3128,p3258,p2680。其中p2680的題解戳這裡。(難度按由低到高排序,再次感謝顧z dalao——我保證這是最後一次了【滑稽】)

差分學習筆記

題面傳送門 首先明確,這是一道差分裸題,不要被它的藍標籤嚇到。演算法簡介 差分是一種和字首和類似的資料結構,畢竟在差分過程中要進行字首和,所以字首和是差分的基礎。差分能做到 o 1 修改,但要 o n 查詢,適用範圍不如字首和。差分適合查詢極少,修改大大多於查詢的題目。演算法實現 首先我們定義差分陣...

差分約束學習筆記

以 luogu p5960 為例。n 個未知數,m 組形如 x i x j le y k 的不等式,求可行解。對於每乙個 x i 我們都能找到 a 組關於它的不等式,第 j 形如為 x i x le y therefore x i le min x y x y x y 該不等式取等時 x i min...

12 20 差分約束學習筆記

先來看一組不等式 x1 x2 0 x1 x5 1 x2 x5 1 x3 x1 5 x4 x1 4 x4 x3 1 x5 x3 3 x5 x4 3 在不等式組 1 中,每個不等式都是兩個未知數的差小於等於某個常數 大於等於也可以,因 為左右乘以 1 就可以化成小於等於 這樣的不等式組就稱作 差分約束系...