原陣列 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相抵消, 還是不變的
因此差分陣列能夠高效的解決區間修改單點查詢的問題。
樹的以下兩個性質:
任意兩個節點之間有且只有一條路徑。
根節點確定時,乙個節點只有乙個父親節點。
如果假設我們要考慮的是從u
到v
的路徑,u
與v
的lca
是a
,,我們將路徑拆分成 u->a和
a->v
如果題目要求對樹上的一段路徑進行操作,並詢問某個點或某條邊被經過的次數,樹上差分就可以派上用場了。
設原陣列為a
,差分陣列為d
。假如給d[i]+1
,其實就相當於給a[i]~a[n]
每個元素+1
如果給樹上的乙個節點x
的d[x] +1
, 相當於a[root]~a[x]
鏈上的每個節點都+1
假設a=lca(x,y)
。 把鏈x~y
分成兩個鏈,x~a
和a~y
。即d[x]+1,d[y]+1
。
但這樣鏈a~root
增加了2
,我們讓d[a]-1
,此時fa[a]~root
變成了-1
,需要d[fa[a]]-1
完美解決。
例題:松鼠的新家(luogu p3258
)
descriptioninput
output
input
output5
1 4 5 3 2
1 22 4
2 34 5
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]
代表從i
到i
的父親這一條路徑經過的次數。令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的區間...