CDQ分治正確的入門姿勢

2021-08-07 08:19:27 字數 1971 閱讀 2762

cdq分治(陳丹琦分治)的思想就是降維。

先來看個題:

1.在數軸上(1~1e9),初始化每點為0。兩種操作:1 a  b(將點a加b),2 a b(詢問區間a—b值的總和)。

很快會想到線段樹或樹狀陣列,因為區間過大,所以離線化一下就好了,這裡因為字首和需要,說以我們就使用樹狀陣列。先把操作2才分開記錄下詢問的id編號,這個詢問的答案就是兩個字首和相減,這裡我們來深層的挖一下這麼做的原因:其實這裡有兩個維度:位置x和時間t,時間t是按輸入順序自動排序好的,所以我們容易忽視時間t維度,其實時間維度與位置維度是完全一樣的,我們不妨按位置x排序(同樣把操作2分開,操作1和操作2丟在一起排),按時間t來樹狀陣列,也會得到正確答案。這是為什麼呢?因為不管我們是按位置做排序時間做樹狀陣列,還是按時間排序按位置做樹狀陣列,都是得到的兩個維度字首和的相交部分(可能解釋得不太到位0.0,請見諒)。

總結上面這題,就是:時間t維度和位置x維度,乙個維度排序,另乙個維度用樹狀陣列。

此時進入正題,再來看一題:

2.在平面上,(x,y:1~1e9),初始化每點為0。兩種操作:1 a b c(將點a,b加c),2 a1 b1 a2 b2(詢問矩形區域a1,b1—a2,b2值的總和)。

很快就會想到二維線段樹或二維樹狀陣列再加個離散化,但是如果詢問次數大於10000,離散化後可能還要開20000*20000的空間,所以最多只能開一維的樹狀陣列,參考上一題的降維解法,這一題有3個維度:時間t 位置x 位置y,我們二分t維度,排序x維度,樹狀陣列y維度,就可以成功降維了。

總結上面這題:通過二分,排序,樹狀陣列降維。

分析上面這題:每個維度是可以字首思想來處理的 才可以用這個方法!因為只有這樣,前面的修改操作才會有且僅有一次地影響到後面的查詢操作(可能解釋得不太到位0.0,請見諒)。

下面再來看一題:

3.在空間上,(x,y,z:1~1e9),初始化每點為0。兩種操作:1 a b c d(將點a,b,c加d),2 a1 b1  c1 a2 b2 c2(詢問長方體區域a1,b1,c1—a2,b2,c2值的總和)。

參考上面一題降維解法,這一題有4個維度:時間t 位置x 位置y位置z,我們二分t維度,二分x維度,排序y維度,樹狀陣列z維度,就可以成功降維了。

下面是與第3題類似的一題:

分析看上面,**看下面0.0,個人覺得這**足夠清晰,不用加多餘注釋,哈哈。

#include#include#include#include#include#include#include#include#include#include//#pragma comment(linker, "/stack:1024000000,1024000000");

using namespace std;

#define inf 0x3f3f3f3f

struct node

node(int _x,int _y,int _z,int _k,int _id):x(_x),y(_y),z(_z),kind(_k),id(_id){}

};vectorq,q1,q2;

vectormdzz;

int ans[500005],c[500005];

void init()

bool cmp(node a,node b)

void countstar()

for(int i=mid+1;i<=r;i++)

sort(q2.begin(),q2.end(),cmp1);

countstar();

}void cdq(int l,int r)

for(int i=mid+1;i<=r;i++)

sort(q1.begin(),q1.end(),cmp);

cdq1(0,q1.size()-1);

}int main()

{ int t;

scanf("%d",&t);

while(t--)

{int n;

scanf("%d",&n);

init();

for(int i=0;i

CDQ分治(初步入門)

cdq分治,傳說中是乙個神犇創造的演算法。分而治之,將原問題不斷劃分成若干個子問題,直到子問題規模小到足以直接解決 子問題間互相獨立且原問題形式相同,遞迴求解這些子問題,然後將各子問題的解合併得到原問題的解 一般步驟 劃分 divide 將原問題劃分成若干子問題,子問題間互相獨立且與原問題形式相同 ...

樹狀陣列模板 cdq分治入門

開始學cdq分治,然後看到了 stdcall的部落格,然後發現從前打過的歸併排序求逆序對就是乙個典型的cdq分治。大致思想就是先按照一維來排序,然後按照第一維的順序進行分治。然後在分治的過程中保證在第一維下左半部分永遠小於右半部分,然後就利用這個性質在左半邊右半邊分別按照第二維度排序,由於左邊和右邊...

CDQ分治的巢狀

簡單地說,有的問題,如果用一重cdq來分治乙個維度後,在合併時,還無法僅借助一層資料結構 如樹狀陣列 來計算左區間對右區間元素的影響。那這時,我們可以選擇再用一重cdq來分治下一維度,達到再降維的效果。hdu上的一道題,stars。題意三維空間下,有兩種操作,1.加入乙個點 2.查詢當前指定長方體空...