目錄一類特殊的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...