離線分治 整體二分與CDQ分治

2022-07-21 01:00:26 字數 2114 閱讀 1836

這兩個演算法都是離線的分治演算法。其中cdq分治是基於時間的分治演算法。整體二分是基於值域的分治演算法。先講講整體二分吧。

我們拿[zjoi2013]k大數查詢作為例子。

一、原理:將所有的修改和查詢操作離線存下來。每次二分所有修改和詢問操作,分成兩部分解決。

二、每個子問題:slove(front,last,l,r)表示在front到last的操作中,答案在l到r中找。要求給每個question找到答案。

三、實現過程:我們要考慮這些新增操作對詢問的影響。在新增操作時,我們把新增到的有影響的地方(即大於mid);在詢問時,查詢詢問區間比mid大的數量。接下來我們的目標是把所有操作歸兩類繼續遞迴。操作值不大於mid的新增和找到比mid大的數大於k的詢問放在第一類(這裡k-=cur),其餘的放在第二類。然後遞迴即可。

四、細節錯誤:

遞迴結束條件:if (front>last||l>r) return;

不開ll見祖宗。

len1,len2不能開全域性,會變的。

五、**實現:(線段樹部分略。)

long long cur[50005];

inline void solve(int front,int last,long long l,long long r)

return;

} long long mid=l+r>>1;

for (rint i=front;i<=last;i++)

for (rint i=front;i<=last;i++)

int len1=0,len2=0;

for (rint i=front;i<=last;i++)

else

}int cnt=front-1;

for (rint i=1;i<=len1;i++) q[++cnt]=q1[i];

for (rint i=1;i<=len2;i++) q[++cnt]=q2[i];

solve(front,front+len1-1,l,mid);

solve(front+len1,last,mid+1,r);

}

六、練習

[國家集訓隊]矩陣乘法 把初始值看做是新增操作,用二維樹狀陣列維護即可。

接下來講講cdq分治。

我們拿【模板】三維偏序(陌上花開)舉例子。這道題還有其他做法,如各種樹套樹和kd-tree。但是今天講的是cdq分治。

零、前置:二維偏序/歸併排序/樹狀陣列(或線段樹)

p.s.作者此處使用樹狀陣列進行敘述。個人推薦使用樹狀陣列而不是線段樹。

我們先不著急考慮三維,先看看二維是怎麼做的。對第乙個關鍵字排序,然後求第二個關鍵字的順序對就好了。

一、分析

我們仍然\(x\)為第一關鍵字排序,\(y\)第二\(z\)第三。這樣第一維都滿足左邊小於右邊了。

我們考慮每乙個子問題。我們把每個子問題分成兩部分進行計算,左邊和右邊都按照\(b\)為第一關鍵字歸併排序。因為我們要計算的是這個子問題的總答案,所以說兩個小子問題的答案我們已經得到了。現在就是要算出跨越兩端之間的貢獻。很顯然,因為\(a\)排過序,因此左邊任何乙個\(a\)一定小於右邊任何乙個\(a\)。我們在歸併排序的時候計算它的貢獻。左指標為\(j\),右指標為\(i\)。若\(b_j,那麼\(j\)可以為以後的做貢獻,把\(c_j\)加入樹狀陣列;否則,在\(j\)以後的\(j'\)都無法為\(i\)貢獻了,那麼計算\(i\)的總貢獻,即\(c_i\)的字首和。

樹狀陣列在這裡起到的作用是單點修改,區間詢問。因此很明顯樹狀陣列比線段樹方便的多。

二、細節

cdq分治在此題中還有個問題。對於兩個完全一樣的東西,我們需要把它們合併。

三、**

bool cmp2(point x,point y)

b[i].ans+=ask(b[i].z);

} for (int i=l;i四、例題

p4169 [violet]天使玩偶/sjy擺棋子

我們先考慮每次查詢時左下角的部分。現在可以看出有三個要求:時間,x和y。這三個值都比詢問小的修改是有用的。這樣就可以三維偏序了。這裡要解決的是\(x_j+y_j\)的最大值,用樹狀陣列維護即可。最後把地圖翻轉每次cdq就可以了。

這題時間卡常,所以加一些優化,比如不用重新排序,從備用陣列裡複製就可以。再卡卡常就過了。

CDQ分治 整體二分

ps 2683 1176是雙倍經驗題 題意 一種操作一種詢問 1,x,y,a 表示將 x y 點值加上a 2,x1,y 1,x2 y2 表示詢問以 x 1,y1 為左上角 x 2,y2 為右下角的矩陣內點和。題意 給定一堆花,每個花有三個屬性,定義一朵花比另一朵花美麗當期僅當三個值都大於等於另一朵花...

CDQ分治 整體二分

cdq分治本質就是分兩半,分別計算兩邊區間的貢獻,然後再考慮跨區間的貢獻。具體教程網上一搜一大把 題單 51nod 1376 考慮用 f i 記錄以i結尾的最長上公升子串行的長度 個數,然後每次切兩半,先計算 l,mid 的答案,然後按照原陣列a的值進行排序,從前往後掃,如果下標在前一半區間則更新乙...

cdq分治 整體二分 學習筆記

本部落格還是從二維偏序開始鋪墊,對cdq分治進行講解 實際上是給自己講,因為沒人看 前置知識 歸併排序 cdq分治的學習需要保證對歸併排序的理解,雖然它是乙個基礎演算法。給定 n 個元素,第 i 個元素有兩個屬性 a i 和 b i 設 f i 為滿足 a j leq a i,b j leq b i...