(正經題解在後面)斜體字都是一年前在沒有把cdq扯清楚的情況下應付的,即使現在真正理解了cdq,還是將這堆話留在這,畢竟,花無重開日,人無再少年——
runid
user
problem
result
memory
time
language
code_length
submit_time
2374693
2711694897
3262
accepted
6376 kb
1632 ms
c++/edit
1851 b
2017-10-23 19:52:20
2374687
2711694897
3262
accepted
6376 kb
3160 ms
c++/edit
1852 b
2017-10-23 19:50:45
先說點題外話:一張圖告訴你函式開銷有多大,用過載的"<"運算子替換乙個cmp函式可以省接近50%的時間!!!就兩行的cmp函式都能帶來如此大的代價orz。回頭再看noip漸漸開始卡常數,以後只要思路清晰不影響排版,能不寫函式就不寫函式吧。。。
題解:
比較模板化的三維偏序。
第一維排序,第二維cdq分治,第三維樹狀陣列。
每一次處理[l,mid]對[mid+1,r]的影響時,比較第二維,查詢第三維(因為[l,mid]區間的x一定小於[mid+1,r]區間的x,第三維用樹狀陣列維護滿足條件的個數),當第二維符合要求時,將它加入樹狀陣列中。每次更新[mid+1,r]區間的乙個ans(記得處理完後還原樹狀陣列)。
正解:cdq分治+樹狀陣列
先對第一維a排序,於是這一維後面可以先不管。
對第二維b進行cdq分治,將區間[l,r]二分成[l,mid]和[mid+1,r],用雙指標掃左右區間,i掃左區間,j掃右區間。(最不好敘述的操作來了)用所有滿足p[i].b<=p[j].b的i在樹狀陣列
p[i].c處
進行add操作(加上i的出現次數,不一定是加1),然後用對應的p[j].c在樹狀陣列中去查詢(注意:所有add過的每次移動j指標前要減回去)。
雙指標每掃一遍為o(n),把遞迴每一層都算上的話相當於掃了logn次,所以總複雜度為o(nlogn)。
問的是嚴格不大於自己的元素有i個,這樣的元素有多少個(這種問法比較適合用定語從句來說233),所以cdq分治完後還有稍微轉換一下得到答案f陣列。
注意:必須先cdq函式中必須先遞迴處理左右子區間再處理當前區間。因為按照第二維b排序是會打亂原本第一維a的公升序的!!!如果先處理當前區間,那麼等你sort兩下在操作一波再遞迴子區間時子區間已經不滿足第一維a公升序了。但是如果先處理子區間,無論你子區間那一層怎麼排,當前層的第一維a仍然滿足左區間小於右區間,這才可以放心大膽地去操作後兩維。
#include#include#include#includeusing namespace std;
const int n=1e5+4;
int c[n<<1],n,nn=0,lim,f[n];
struct node
inline void add(int x,int val)
inline int query(int x)
void cdq(int l,int r)
for (int k=l;k}int main()
cdq(1,nn);
for (register int i=1;i<=nn;++i) f[p[i].ans+p[i].rep-1]+=p[i].rep;
for (register int i=0;ireturn 0;
}
BZOJ3262 陌上花開 CDQ分治
對第一關鍵字排序,分治每朵花,合併的時候通過歸併左右的花的第二關鍵字,將值插入樹狀陣列中求值。對於相同的花,先進行預處理即可。include bits stdc h define lowbit x x x using namespace std const int n 100005,m 200005...
bzoj 3262 陌上花開(cdq分治)
time limit 20 sec memory limit 256 mb submit 1431 solved 644 submit status discuss 有n朵花,每朵花有三個屬性 花形 s 顏色 c 氣味 m 又三個整數表示。現要對每朵花評級,一朵花的級別是它擁有的美麗能超過的花的數量...
BZOJ 3262 陌上花開 CDQ分治
最近又研究了一下cdq分治,發現比樹套樹好寫多了啊。首先cdq分治只能優化掉一維,對於乙個三維問題,cdq分治先二分第一維,然後通過sort第二維後由左到右掃瞄確保第二維的順序,第三維則需要乙個計數的資料結構維護,一般是樹狀陣列或者線段樹,然後就完美地解決掉了問題。而對於cdq遞迴時,可以採用先序遍...