分治算法
一、二分
二分本質是求邊界
一定面對有序的,可以是大小,也可以是性質
你看這個二分查找
寫好二分
首先你要有好模板
典型例題
1.借教室
打標記(差分維護前綴和)
O(1)打標記,O(n)求前綴和
O(m)是訂單數
O(m+n)求出每天需要多少教室
2.
解析
在數字1~num中,
u表示能被x整除的數的個數
v表示能被y整除的數的個數
w 表示能被x*y整除的數的個數
因為在[1, num]里面,只有x,2x,3x,4x...
這么幾個數能被 x 整除,而且對於 kx,需要保證 kx <= num
所以顯然 k = floor(num / x)
二、三分
復雜度:log3/2N
如何比較兩個實數的大小呢?? 如果我們有兩個數字 a,b 經過一系列玄學操作 a,b在計算的時候精度可能會丟失 此時做差判斷他們到底誰大 double eps=1e-8; fabs(a-b)<eps return 0; //表示a=b return a-b<0?-1:1;
那如果函數不是單峰怎么辦?
三、分塊
1.給出一個長度為n的數列,以及m個操作,支持區間加法,單點查詢
(PS,為什么不用線段樹??)
我們分塊!!!
吧長為n的數組分成√n個塊
給出詢問區間 [ L , R ]
情況1:L,R在同一塊里,暴力跑
情況2:L,R在相鄰塊里,暴力跑
情況3:L,R在不相鄰塊里,L~R之間每個塊打標記
單點查詢:自己加標記
2.給出一個長為n的數列以及m個操作,支持區間加法,並詢問區間內小於等於某個數x的元素個數
長度為n的數列a,我們把它分塊到b數組,√n一個塊,然后每個塊內部進行排序
(1) 給出詢問區間 [ L , R ]
還是考慮三種情況
情況1:L,R在同一塊里,暴力掃描 O(√n)
情況2:L,R在相鄰塊里,暴力掃描 O(2√n)
情況3:L,R在不相鄰塊里 O(√n log n)
(2) 區間加
L,R在一個塊里就直接加啊,然后跑一遍快排 O(√n log n)
但是它的復雜度可以再低一點,達到
用均值不等式調整分塊大小,查詢復雜度和修改復雜度取均值不等式
3.給出一個長為n的數列以及m個操作,支持區間開放,區間求和
一個longlong 最多開方6次變1
掃描區間,若是01的一段區間,就標記,以后開方不用動了,因為不會改變了呀
假設你有一堆彈珠
紅黃藍綠紅綠藍紫粉黃粉藍
color[i]:下標為i的球的顏色
pre[i]:前一個顏色為color[i]的球的下標編號
引理:
如果 pre[i]<x<i,那么在區間[x,i]之間有一個顏色為color[i]的球
so,
查詢區間[l,r]里有多少不同顏色,等價於
查詢區間[l,r]之間pre[i]<l的i的個數
也就是求[l,r]里有多少個pre[i]<l
這個可以用上面講的2做
O(n)暴力修改能過
題外話
推薦oj
1.CF(cross fire(不是)) CodeForce
2.CodeChef(對高中生還算友好)
3.TopCoder
4.Div2