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.查詢當前指定長方體空...