BZOJ1173 CDQ分治 筆記

2022-03-26 01:01:44 字數 2395 閱讀 6354

目錄一類特殊的cdq分治

附: bzoj mokia ac**

偏序關係 link1

資料結構 link1, 高階指南p212

雜燴 link1

hdu1892

一維樹狀陣列: 二進位制分段思想

可以把\(m = 2^a+2^b+\cdots(a>b>\cdots)\) 分解成\((0, 2^a], (2^a , 2^a+2^b]...,(m - 2^z+1, m]\)這log個區間, 所以對於每個\(x\)存\((x-lowbit(x), x]\)

二維樹狀陣列也是這樣, 每一行的元素維護的是之前\([x-lowbit(x)+1, x]\)列該位置元素的和

所以只要在普通樹狀陣列上再加一維就好啦

例子: 求逆序對(這個經典問題在很多oj上都有)

有句話叫羅馬不是一天建成的, cdq分治也不是憑空想出來的,該演算法與 求逆序對的兩種做法有很深的關聯.

逆序對的定義是 一對數\((i, j),ia[j]\) 所以我們把求逆序對問題轉換為統計在x之前比x大的數有多少個這一問題 這種問題是二維偏序問題的一種(意思是要統計滿足兩個序的元素個數)

第二種做法就很妙了.

我們可以發現, 如果數字排好序了, 值就很方便算(為0). 但是問題是, 我們打破了題目的乙個限定(i關鍵是, 我們不一定需要將所有數字都排好序啊!!! 我們只需要讓滿足\(i的數在數\(j\)之前出現就可以了啊!!!

所以有乙個解決方法是用分治來"去掉"\(i這個"序"所帶來的不方便之處. 我們可以將數分成兩半, 分別統計出每一半內的答案, 之後再排好序, 求出每乙個數的答案, 然後算前面的數對後面數字答案的影響. 此時, 前面一半和後面一半的所有數之間, \(i這個"序是成立的. 而在每一半數內, 答案已經求出,所有我們就可以把這一半內數字的第一維"序"(\(i)打亂, 按照第二維序(\(a_i)排序. 這樣我們就可以方便的求出答案啦!!

(其實離線演算法就是可以忽略時間的影響直接對x或y排序的演算法)

強不強大?

有幾個小技巧:

統計答案時用指標把每乙個詢問用指標對映到陣列, 方便統計答案.

見歸併**

static op tmp[siz];

for(int pos = l, i = l, j = mid+1; pos <= r; pos++) else

}

習題 :bzoj1176 mokia

讀入單個字元用cin 不用scanf

不要貿然進行一些不確定的優化

給出偽** 思路不寫了

//處理: 如果floyd不考慮[l, r] 的話, dis陣列會是怎麼樣

//將陣列存入tmp_d[dep]中

void cdq(int l, int r, int dep)

#includeusing namespace std;

templatevoid read(t &ans)while( isdigit(c))ans *= f;}

const int mxm = 16*1e4, mxq = 1e4, mxw = 2e6;

struct opops[mxm+mxq*4+1];

op getop(int x, int y, int a, int typ)

op getop(int x, int y, int d, int *ans, int typ)

bool isquery(op x)

int s, w, ans[mxq+1];

int c[mxw+5];

int query(int x)

void add(int x, int v)

void clr(int x)

void work(int l, int r) else

}

// puts("end.");

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

// for(int i = 1; i <= 10; i++)if(query(ops[i].y) != 0) printf("when l = %d, r = %d, faaaa!!!! on %d, get %d\n",l, r,i,(query(ops[i].y)));

}signed main() else if(op == 2)

}// for (int i = 1; i <= cnt; i++)

work(1, cnt);

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

return 0;}/*

0 200

1 76 150 1

1 158 170 2

1 12 4 123

2 92 59 153 141

3*/

cdq分治 筆記

部落格觀賞效果更佳 github cnblogs 這個演算法用於解決三維偏序問題。三維偏序 給定 n nn 個三元組 ai bi,ci a i,b i,c i ai b i c i 求同時滿足滿足 ai aj,b i bj ci cja i le a j,b i le b j,c i le c j ...

學習筆記 CDQ分治

分治,考慮前一半對後一半的影響。和一般分治不太相同的思想是,一般分治不分誰對誰的影響,跨mid的都要統計。全域性變數統計 而cdq貌似要落腳到前一半對後一半的影響上,也就是貢獻在後一半統計,由前一半產生。大概使用情況 1.三維偏序 2.優化dp 3.這個裡面有。注意處理三維情況的巧妙性。heoi20...

學習筆記 CDQ分治

聽娜姐講完fft,一臉懵逼,還是來講講 cdq分治 吧。解決 帶時間軸的更改和查詢 問題。首先我們要知道,這個演算法是離線的,還是利用遞迴進行求解的。把讀入的n個操作都按照時間軸排列好。把時間軸劈開,分為 l,mid 和 mid 1,r 兩部分。開始當前層cdq l,r 的求解前先進行cdq l,m...