CDQ分治總結

2022-05-08 06:27:12 字數 4048 閱讀 9124

目錄同步:

經過了一周的划水,我終於搞懂了cdq分治。

總的來說,cdq分治處理偏序問題就是

傳送門求靜態區域內的點數,二維偏序模板題。

#include#includeconst int maxn = 500000 * 5 + 5;

//x,y:橫縱座標

//type:操作型別

//add:求矩形區域面積用幾個矩形加加減減,所以add表示一下正負

//id:詢問的id,因為乙個詢問拆成了好幾個

//ans:存當前詢問對應的答案

struct node a[maxn], tmp[maxn];

int n, m, newp;

int ans[maxn];

void add (int x, int y, int type, int add, int id, int ans) ;

}bool cmp1 (node x, node y)

return x.y < y.y;

} return x.x < y.x;

}void cdq (int l, int r)

int mid = (l + r) >> 1;

cdq(l, mid);

cdq(mid + 1, r);

//左半邊處理好了,把左半邊所有修改加到右半邊的詢問中去

int newl = l, newr = mid + 1, pos = l, ans = 0;

//對於這個區間的上層區間,左邊的x肯定都小於右邊,所以這裡按y排序後塞回a

while (newl <= mid && newr <= r)

tmp[pos++] = a[newl++];

} else

tmp[pos++] = a[newr++];

} }//沒處理完的別剩著

while (newl <= mid)

while (newr <= r)

tmp[pos++] = a[newr++];

}//按y排好的結果裝入a

for (int i = l; i <= r; ++i)

}int main (void)

for (int i = 1; i <= m; ++i)

std::sort(a + 1, a + 1 + newp, cmp1);

cdq(1, newp);

for (int i = 1; i <= newp; ++i) }

for (int i = 1; i <= m; ++i)

return 0;

}

傳送門

把操作出現的時間看做是第一維即可。

對於後面的數修改不會影響到前面的字首和。

#include const int maxn = 500000 + 5;

struct node

} a[maxn * 3], tmp[maxn * 3];

int n, m, newp;

int ans[maxn * 2];

void cdq(int l, int r)

int mid = (l + r) >> 1;

cdq(l, mid);

cdq(mid + 1, r);

int i = l, j = mid + 1, p = l, sum = 0;

while (i <= mid && j <= r)

else

tmp[p++] = a[j++];

} }while (i <= mid)

while (j <= r)

tmp[p++] = a[j++];

} for (int i = l; i <= r; ++i)

}int main (void)

int opt, x, y, z, anscnt = 0;

for (int i = 1; i <= m; ++i)

else

} cdq(1, newp);

for (int i = 1; i <= anscnt; ++i)

return 0;

}

為什麼我要把「陌上花開」寫在前面呢?因為這樣看起來比較帥

第一維排序,第二位像原來那樣比大小,然後搞個值域樹狀陣列來統計每個0~x裡的第三維

要去重

#include #include const int maxn = 200000 + 5;

namespace sz

int c[maxn * 2];

void add (int x, int k)

} int query (int x)

return ans; }}

struct node a[maxn], tmp[maxn];

int n, k, newp;

int size[maxn], ans[maxn], num[maxn];

bool cmp1 (node x, node y)

void cdq(int l, int r)

else

} while (j <= r)

for (int h = l; h < i; ++h)

while (i <= mid)

for(int i = l; i <= r; ++i)

}int main (void)

std::sort(a + 1, a + 1 + n, cmp1);

for (int i = 1; i <= n; ++i)

++size[newp];

} for (int i =1; i <= newp; ++i)

cdq(1, newp);

for (int i = 1; i <=newp; ++i)

for (int i = 0; i < n; ++i)

return 0;

}

傳送門

其實這是 nokia 噠

本來是個二維,加上時間順序就是三維了。

樹狀陣列下標不能為0

#include #include const int maxn = 1700000 + 5;

namespace sz

int c[maxn * 2];

void add (int x, int k)

} int query (int x)

return ans;

} void clear (int x) }}

struct node

} a[maxn], tmp[maxn];

int n, newp, newq;

int ans[maxn];

void cdq(int l, int r)

int mid = (l + r) >> 1;

cdq(l, mid);

cdq(mid + 1, r);

int i = l, j = mid + 1, p = l;

while (i <= mid && j <= r)

else

} while (i <= mid)

while (j <= r)

tmp[p++] = a[j++];

} for (int k = l; k <= mid; ++k)

for (int i = l; i <= r; ++i)

}void read (int &x)

while (t >= '0' && t <= '9')

x *= k;

}int main (void)

else

read(opt);

} //std::sort(a + 1, a + 1 + newp, cmp1);

cdq(1, newp);

for (int i = 1; i <= newq; i += 4)

return 0;

}

CDQ分治總結

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

CDQ 分治總結

特別基礎的教程略。cdq 分治的優缺點 1 優點 量少,常數極小,可以降低處理維數。2 缺點 必須離線處理。cdq 分治與其他分治最本質的不同在於 分治到達 l,r 時,分治處理 l,mid 與 mid 1,r 然後遞迴上來合併的時候 只考慮 l,mid 中元素 對 mid 1,r 中元素的影響 看...

CDQ分治概述

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