1. 程式人生 > >字首和 & 差分

字首和 & 差分

字首和和差分,兩個都是一種優化演算法,把原來甚至需要O(n平方)的演算法變成O(n),可謂優化得十分優秀。那它們倆具體是什麼,我們一起來看

字首和:

可基本分為一維字首和和二維字首和。

  1. 一維字首和:設計狀態f[i]表示i之前(包括i)符合條件的元素個數。這麼說可能有些抽象,我們舉個例子來看:有一個長度為n的序列,如果其中一個元素>=10,就算它是個“好元素”,有q組詢問(x,y),請問對於每組詢問x-y位置中有多少個好元素?看到這道題我們第一反應可能就是暴力列舉,一個一個找看是不是,是就++。但這樣對於多組詢問無疑TLE,所以我們就用f[i]表示i之前(包括i)符合條件的元素個數,然後開始遞推,每次f[i]=f[i-1],如果它自己也符合條件,那麼再f[i]++,最後遞推完後,每一組詢問的答案就是f[x]-f[y-1]
  2. 二維字首和:設計狀態f[i][j]表示以(i,j)為右下角的矩形內合法的元素個數,遞推式就是:f[i][j]=f[i][j-1]+f[i-1][j]-f[i-1][j-1],如果它自己也符合條件,那麼再f[i][j]++,為什麼,畫個圖形就知道了

差分:

差分基本分為線性差分、樹上差分,樹上差分又分為點差分和邊差分。

線性差分:差分適用與區間修改,你可能看到這會說:線段樹!但是沒有多次動態詢問的題目,用線段樹可真謂大材小用。差分是怎麼支援區間修改的呢?我們首先設計一個差分陣列diff和原陣列a,diff[i]表示a[i]應該變化的量。所以假如有數列1、2、3、4、5,我現在要求你將位置2-位置4的每個元素加上3,這時用差分應該怎麼做呢?首先diff[2]+=3,diff[4+1]-=3,為什麼要這樣呢?因為差分也有遞推式:diff[i]+=diff[i-1],所以到時候位置2-4的元素都加了一個3,而第5個元素加了一個3又減了一個3,所以就為0了,後面的元素自然就為0。所以用差分解決區間修改問題的話,第一步對於每組要求:只用頭尾加減即可,第二步要求執行完後遞推差分陣列,最後遞推a陣列,即a[i]+=diff[i]

樹上差分:其實樹上差分跟線性差分一樣,它可以解決什麼問題呢?舉個例子,有一顆樹V,裡面有很多條鏈,請你找出被每條鏈都經過的公共邊。看到這題,暴力我猜你也想到了,這樣100%T飛,所以我們對於每條鏈的起點s和終點e和它們的lca,用一個差分陣列diff,並diff[s]++,diff[e]++,diff[lca(s,e)]-=2,最後遍歷一遍圖(也就是線性差分的遞推),得出diff[i],即邊(i,i的爸爸)被訪問過多少次。這麼說太抽象了。我直接轉別人的一個部落格

  1. 樹上差分講解
  2. 樹上差分模版題(題解)看作者為Sa開頭的那篇

看了然後再做一遍題我相信你就懂了!