CDQ 分治總結

2022-04-29 19:57:10 字數 4124 閱讀 8221

特別基礎的教程略。

\(cdq\)分治的優缺點:

( 1 )優點:**量少,常數極小,可以降低處理維數

( 2 )缺點:必須離線處理。

\(cdq\)分治與其他分治最本質的不同在於:

分治到達\([l,r]\)時,分治處理\([l,mid]\)與\([mid+1,r]\)

然後遞迴上來合併的時候:

只考慮 [l,mid]中元素 對 [mid+1,r] 中元素的影響

看起來這句話非常簡單,但只要正真理解了這句話,也就理解了\(cdq\)分治。

只要是滿足這個原則的分治,都是可以稱作\(cdq\)分治的。

下面給出幾個例子,都是為了理解這句話:

給定長度為\(10^5\)的乙個序列,有一下兩種操作:

(1)type=1:x val ,把序列第x位置的元素加上val

(2)type=2:x y , 求解[x,y]元素值的和

樹狀陣列大水題.....

如果用\(cdq\)分治呢?(雖然非常非常沒有必要).

我們把求解\([x,y]\)元素之和拆分為求字首和\(pre[y]-pre[x-1]\)。

那麼會對\(pre[x]\)產生影響的為:操作時間在其之前,修改位置\(\leq x\)的修改操作

建立二元組\((time , x)\),外部以time排序,然後分治。

分治時,每次以\(x\)歸併排序,

合併\([l,mid]\)與\([mid+1,r]\)時,統計\([l,mid]\)有幾個修改操作。

那麼如果在\([mid+1,r]\)碰到了修改操作,自然此時的統計數即為答案。

注意到上面:只統計[l,mid]的修改,只計算[mid+1,r]的答案

這就是\(cdq\)分治的關鍵所在,因為這樣統計可以做到不重不漏,**見這裡。

三維偏序問題:

給定\(n\)個元素,每個元素有三個屬性\(a,b,c\)。

定義\(f(i) = \sum_^n [i!=j]\times [a_j

試計算\(f(1),f(2),...f(n)\),資料範圍 \(n \leq 10^5\)。

三維偏序是\(cdq\)分治的最經典應用。

先確定分治原則:

建立三元組\((a,b,c)\),外部先按照\(a\)排序,消除\(a\)的影響。

然後分治內部以\(b\)為準則進行歸併。此時我們保證了\(a_j與\(b_j

第三維\(c_j怎麼辦?用以\(c\)值建立權值樹狀陣列維護即可。

具體流程為:

(1)遞迴處理\([l,mid]\)與[mid+1,r];

(2)以\(b\)為準則歸併,其中:

( 2>1 )若為\([l,mid]\)元素,將其\(c\)值插入權值樹狀陣列

( 2>2 )若為\([mid+1,r]\)元素,在權值線段樹中查詢小於其\(c\)值的元素個數。

(3)回溯;

觀察到處理時,依舊滿足上面\(cdq\)分治的特性。

如果偏序原則中為\(\leq\)即可,那麼需要先去重。具體**見這裡

乙個非常大的誤區:\(cdq\)分治一定要歸併或邊歸併邊處理。

這其實是不對的,上面說過,只要滿足\(cdq\)分治原則就可以稱為\(cdq\)分治。

所以\(cdq\)分治的寫法其實是多重多樣,甚至不拘一格的。

\(cdq\)分治中的乙個難點就是確定分治原則。

在我們分治前,我們會確定元素的分治多元組。

分治多元組的確定關鍵是看分治中對答案的影響因素。

下面給兩個非常經典的例題:

序列初始為空,接下來每次會在指定位置\(i\)插入乙個元素\(x\)

求每次插入後,序列中的逆序對個數。

保證插入元素的值不重複,資料範圍\(n \leq 10^5\)

確定三元組\((time , pos , val)\),然後分治:

外部以\(time\)進行排序,消除\(time\)的影響。

然後內部以\(pos\)為原則進行歸併,然後怎麼處理呢?

考慮一下元素對答案的影響:

每次新增的點對此時答案的貢獻為:

(1)插入時間比它早,位置在它前面,值比它大的元素。

(2)插入時間比它早,位置在它後面,值比它大的元素。

所以我們先以\(pos\)從小到大歸併排序好。

然後從前往後正著掃一遍,

如果元素的\(time \leq mid\),那麼在樹狀陣列中插入它的\(val\)。

如果元素的\(time > mid\),那麼在樹狀陣列中查詢大於它的\(val\)的元素個數,加入答案。

然後再從後往前倒著掃一遍,處理方法一樣。

這樣我們最後就得到了每加入乙個元素新增的貢獻數,最後統計一下答案即可。

具體**戳我。

給定乙個大小為\(n*n\)的矩陣,初始每個格仔元素都為\(0\)

一共有\(10^5\)個操作,操作如下:

(1)type=1:x y val ,把(x,y)位置的元素加上val。

(2)type=2:x1 y1 x2 y2, 查詢(x1,y1)到(x2,y2)這個矩形的元素和。

貌似是上面的 例題1 的公升級版....

由二維變為三維,怎麼做呢? 其實差不多。

二維字首和之類的略,自己\(yy\),然後:

建立三元組\((time , x , y)\)

會影響詢問答案的為:操作時間早於其,x、y都小於等於它x、y的修改操作

所以外部以\(time\)排序,然後以\(x\)為原則歸併。

歸併的時候,如果是左邊區間的修改操作,把其修改值\(val\)值插入樹狀陣列中的\(y\)位置。

如果是右邊的查詢操作,查詢樹狀陣列中小於等於其\(y\)值的元素值之和。

這題做完了......

首先我們考慮三維偏序的解決方法:

外圍排序三元組變為\([l,b,c]與[r,b',c']\),然後歸併變為\([l,l,c]與[r,r,c']\)

所以此時只需要在樹狀陣列中查詢\(c\)了。

那麼四維是不是類似呢?

首先外圍排序,四元組變為\([l,b,c,d]與[r,b,c,d]\)

然後我們先以\(b\)為原則歸併,但是並不統計答案。

此時我們要記錄歸併好的序列中每乙個元素的\(a\)是屬於\(l\)還是\(r\)。

那麼此時只有\(b\)是有序的,\(a\)雖然無序但是我們記錄了其**(順序)。

即此時的四元組為\([l/r,l,c,d]\)與\([l/r,r,c',d']\)

此時把這個新的序列帶入下一層\(cdq\)中再跑一遍,不就是三維偏序的處理嗎?

但是這裡注意,為了保證\(a\)的順序,只有\([l,l,c,d]\)與\([r,r,c',d']\)的元素才是合法的。

這個也非常好解決,第一層\(cdq\)歸併時對每個元素打乙個標記即可。

具體的**見這裡

這裡提個醒,用巢狀\(cdq\)解決\(n\)維偏序問題的複雜度是\(o(n\ log^n)\)的。

其實搞懂了四維偏序的解決方法後,五維、六維....不是一樣的嗎?

四維時我們打了一層標記,消除了一維的影響,最終變為了三維偏序問題。

那麼\(n\)維我們則先歸併\(n-3\)遍,打\(n-3\)層標記。

這樣一共消除了\(n-3\)維的影響,然後再跑三維偏序即可。

實現五維偏序的具體**見這裡。

(1)luogu p3374 【模板】樹狀陣列 1

(2)bzoj 3262陌上花開

(3)[shoi2007]tree 園丁的煩惱

(4)[cqoi2011]動態逆序對

(5)[hzoi 2016]偏序

(6)[hzoi 2015]改:偏序 ii

(7)[boi2007]摩基亞mokia

(8)bzoj 4237 稻草人

(9)[noi2007]貨幣兌換cash

CDQ分治總結

cdq這個東西嘛,說容易其實也很容易,說難其實也有些難,但只要細細品味,定能發現其中的真理的!那真理,也會像蝴蝶一般,破蛹而出,化身為一道亮麗的風景線。題記。咳咳,閒話就講到這裡了,切入正題。首先我們來了解一下cdq分治這個東東。cdq分治,他的常數小,但必須離線操作the most importa...

CDQ分治總結

目錄同步 經過了一周的划水,我終於搞懂了cdq分治。總的來說,cdq分治處理偏序問題就是 傳送門求靜態區域內的點數,二維偏序模板題。include includeconst int maxn 500000 5 5 x,y 橫縱座標 type 操作型別 add 求矩形區域面積用幾個矩形加加減減,所以a...

CDQ分治概述

log l og 的時間把它變成離線問題。正好有些題目的離線問題是比較簡單的。具體是什麼意思呢?我們對於每一層分治,只考慮前一半對於後一半的影響,然後在每個詢問當中記錄下來影響。最後把所有影響合併就可以得到每乙個詢問的答案。舉個例子 區間修改區間查詢。首先,在時間軸上離線分治。每一層分治後把詢問和查...