差分 差分陣列 樹狀差分

2022-03-20 01:06:53 字數 3233 閱讀 3091

原陣列 ai94

759差分陣列 bi9-5

3-24差分陣列的字首和94

759顯然通過求字首和可以做到單點查詢

他高效的地方在於區間修改,比如我們對區間[2,4]每個元素加上5,我們只需在差分陣列:b2+=5,b5−=5,然後求字首和即可

原陣列 ai94

759差分陣列 bi

903-2

-1

差分陣列的字首和99

1210

9[1,2]仍不變, [2,4]的字首和都加了5, 4以後的話+5,-5相抵消, 還是不變的

因此差分陣列能夠高效的解決區間修改單點查詢的問題。

樹的以下兩個性質:

任意兩個節點之間有且只有一條路徑。

根節點確定時,乙個節點只有乙個父親節點。

如果假設我們要考慮的是從uv的路徑,uvlcaa,,我們將路徑拆分成 u->aa->v

如果題目要求對樹上的一段路徑進行操作,並詢問某個點或某條邊被經過的次數,樹上差分就可以派上用場了。

設原陣列為a,差分陣列為d。假如給d[i]+1,其實就相當於給a[i]~a[n]每個元素+1

如果給樹上的乙個節點xd[x] +1, 相當於a[root]~a[x]鏈上的每個節點都+1

假設a=lca(x,y)。 把鏈x~y分成兩個鏈,x~aa~y。即d[x]+1,d[y]+1

但這樣鏈a~root增加了2,我們讓d[a]-1,此時fa[a]~root變成了-1,需要d[fa[a]]-1完美解決。

例題:松鼠的新家(luogu p3258)

description

input

output

input

5

1 4 5 3 2

1 22 4

2 34 5

output
121

21

#include using namespace std;

const int maxn=3e5+5;

struct edgee[2*maxn];

int n, len, a[maxn], head[maxn], dep[maxn], f[maxn][21], sum[maxn];

void insert(int u, int v)

void dfs(int u, int fa)

if(u==v) return u;

for(int i=20; i>=0; i--) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];

return f[u][0];

}void search(int u)

}int main()

dfs(1,0);

for(int i=1; i<=n-1; i++)

search(1);

for(int i=2; i<=n; i++) sum[a[i]]--;//2-n的點都多算了一次

for(int i=1; i<=n; i++) printf("%d\n",sum[i]);

return 0;

}

cf[i]代表從ii的父親這一條路徑經過的次數。令a=lca(u,v)因為關於邊的差分,a表示a到其父親的那條邊,不在u~v路徑中,所以cf[u]++,cf[v]++,cf[a]−=2

思路最小的長度, 肯定在 0 - maxl(最長的那條道路) 之間, 我們可以用二分在 0-maxl列舉, 每次列舉統計長度超過mid的路徑的條數cnt, 找到一條被經過了cnt次的邊(這條邊可以影響所有長度超過mid的路徑), 把符合條件的邊中最長的那一條歸零, 如果cnt條路徑中最長的減去這條邊權<=mid, 則當前的mid合法.

#include using namespace std;

const int maxn=3e5+5;

int f[maxn][22],head[maxn],edge[maxn],dep[maxn],dis[maxn];

int st[maxn],ed[maxn],c[maxn],lca[maxn],len[maxn];

int n,m,lene,maxl,ans,cnt,max_edge;

struct edgee[maxn<<1];

void insert(int x,int y,int z)

void dfs(int u)

if(u==v) return u;

for(int i=20; i>=0; i--) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];

return f[u][0];

}int getdis(int i) //求第i條路徑長度

int dfs2(int u)

if(tot==cnt) max_edge = max(max_edge, edge[u]);

return tot;

}bool check(int mid)

int main()

printf("%d\n",ans);

return 0;

}

差分樹狀陣列

一 假設現在有乙個原陣列a 假設a 0 0 有乙個陣列d,d i a i a i 1 那麼 a i d 1 d 2 d i d陣列就是差分陣列 所以求a i 就可以用樹狀陣列維護d i 的字首和 即維護的是d i 的樹狀陣列 上面的數學思想可以實現區間修改,以及單點查詢。下附上 區間修改 1 n v...

樹狀陣列與差分

1.什麼是樹狀陣列?顧名思義,就是用陣列來模擬樹形結構唄。那麼衍生出乙個問題,為什麼不直接建樹?答案是沒必要,因為樹狀陣列能處理的問題就沒必要建樹。和trie樹的構造方式有類似之處。2.樹狀陣列可以解決什麼問題 可以解決大部分基於區間上的更新以及求和問題。3.樹狀陣列和線段樹的區別在 樹狀陣列可以解...

差分詳解 樹狀陣列擴充套件

前言 現在還不是很懂,不過先把模板抄在這裡把。介紹一下差分,乙個很簡單的東西。一 簡介 已知陣列a為1,2,1,5,7,4 那麼差分陣列1,1,1,4,2,3 顯然,差分陣列就是當前項與前一項的差值。容易得到,an就是差分陣列的前n項和。二 那麼有什麼便利的地方呢?我們假想一下,現在要給1至4的區間...