目錄同步:
經過了一周的划水,我終於搞懂了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 的時間把它變成離線問題。正好有些題目的離線問題是比較簡單的。具體是什麼意思呢?我們對於每一層分治,只考慮前一半對於後一半的影響,然後在每個詢問當中記錄下來影響。最後把所有影響合併就可以得到每乙個詢問的答案。舉個例子 區間修改區間查詢。首先,在時間軸上離線分治。每一層分治後把詢問和查...