cdq分治小結

2021-09-25 10:27:43 字數 1338 閱讀 4929

一般的分治,眾所周知的,是通過將大的問題拆小,然後對小問題的答案進行合併得到大問題的答案,但是cdq分治不是。我們知道,分治時,將乙個區間從中間斬開,分兩半處理,cdq分治在處理完之後,不是合併答案,而是計算左區間對右區間的貢獻,這樣子可以將維度降低,問題就更好做了。

現在有 n

nn 個二元組,每個形如 (a,

b)

(a,b)

(a,b

),現在問有多少對二元組之間是吊打的關係。ps:x

xx 吊打 y

yy 的定義是x的a>y的a , x的b>y的b

大佬瞟一眼就能發現,這就是逆序對問題嘛。

我們對關鍵字 a

aa 進行排序,這樣我們就可以忽略 a

aa 的影響了,後面用權值樹狀陣列即可求解。

可見,排序是一種強大的降維**!

問題公升級!

現在有 n

nn 個三元組,每個形如 (a,

b,c)

(a,b,c)

(a,b,c

),現在問有多少對三元組之間是吊打的關係。ps: x

xx 吊打 y

yy 的定義是x的a>y的a , x的b>y的b , x的c>y的c

我們發現,用排序進行降維之後,還剩下兩維呀!而排序這個**是顯然只能用一次的,那對於二元組顯然也難以求解,於是,我們還需要降維,用誰呢?

神奇的cdq分治登場!

依照上面的思想,我們可以對關鍵字 b

bb 進行分治,每次將序列分成兩半,將這兩半分別按照關鍵字 b

bb 排序,那麼現在我們知道,左邊部分的 a

aa 都小於右邊部分的 a

aa(假設我們從小到大排序),那麼我們只需要將左邊部分中 b

bb 也小於右邊部分 b

bb 的那些加入權值樹狀陣列,然後統計答案即可。

(這麼說我自己都覺得抽象。。) 那麼來看看**吧!

void

solve

(int x,

int y)

for(

int i=x;i)//清空樹狀陣列

add(a[i]

.z,-a[i]

.w);

}

當然,cdq分治的強大之處還不止這樣,它不僅和排序一樣可以降一維,它還比排序要厲害一些——它可以巢狀!

這樣,就可以降更多維了,而時間複雜度僅僅是隨著巢狀層數增加若干個log而已!而且,空間上完全無負擔。

具體做法可能以後會補上吧qwq,這裡先坑一下了

CDQ分治小結

一道cdq分治的比較模板又不是模板的問題.設 f i 表示 a j a i 且 b j b i 且 c j c i 的 j 的數量 對於 d in 0,n 讓你求 f i d 的數量 其實個人感覺模板的話 還是嚴格小於比較好做 先來考慮一下嚴格小於該怎麼做 我們先對整體按照 a i 排序,這樣的話我...

cdq分治學習小結

一臉懵逼的學了好久,應該算學會了吧。基本了解cdq分治的思想,然而 一如既往的醜。cdq分治只支援離線操作,主要作用是降維,反正就是大大優化了時間和空間。感覺不扯幾句作用非常不好 輸入長度為n的序列,並進行m次操作,操作分兩種 1.將編號為的數加上y 1 x y 2.求出某區間每乙個數的和 2 x ...

CDQ分治概述

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