菜雞今天又開始了乙個新的演算法,廢話不多說,開始筆記。二分查詢是乙個十分常用的演算法,適用於對帶有單調性的資料進行處理或查詢。大多數題目可能沒那麼顯示,需要自己來找這個單調性在哪,所以這就是乙個重點,具體的用法和**很簡單,就那麼幾行,但是對於折半的條件卻需要有嚴格的要求。
[牛客]完全平方數
就如這個題目:多次查詢[l,r]範圍內的完全平方數個數。這樣的題目通常需要經過預處理。因為資料量看起來比較大1e9,你也沒法預處理哪個數是不是完全平方數。但是,完全平方數嘛,就必然是乙個數的平方,那我們可以存一下,每乙個數對應的完全平方數是誰。如:1->1,2->4,這樣以此類推,正好我們的下標的平方就是我們儲存的資料。而且我們也正好可以知道從1到這個數,已經有多少個完全平方數了,有點字首和的感覺,這樣,我們每遇到乙個區間就可以直接二分查詢兩個端點的位置,然後做差,就正好是這個範圍內所求性質的數的個數了。這裡要注意一下,最好是要在二分查詢的時候用左閉右開,這樣你後面那個查到的永遠是比你右端點大的位置,用這個直接減掉左端點就是其中數的個數了。
總結一下,我們的思想就是,大資料我們存不下,我們可以把某些具有該特性的數預處理先存在陣列裡面,借助陣列下表當做字首和,來相當於把乙個大的區間進行了離散化,在進行二分查詢。
#include
#include
#include
using
namespace std;
long number[
100010];
intmain()
return0;
}
**很簡單的,對吧~
01分數規劃的題目可以借助二分進行近似求解。至於什麼是01分數規劃,在這裡稍微簡單做下筆記,當然可以問度娘。
0/1分數規劃模型是指,有一些二元組(si,pi),從中選取一些二元組,使得∑si / ∑pi最大(最小)。
這種題一類通用的解法就是,我們假設x = ∑si / ∑pi的最大(小)值,那麼就有x * ∑pi = ∑si ,即∑si - x * ∑pi= 0。也就是說,當某乙個值x滿足上述式子的時候,它就是要求的值。所以我們直接二分答案,當上述式子》0,說明答案小了,<0則說明答案大了,這樣計算即可。
[牛客]wyh的物品
#include
#include
#include
#include
using
namespace std;
const
int maxn =
1e5+5;
const
double eps =
0.001
;double v[maxn]
, w[maxn]
, x[maxn]
;int
main()
double mid, sum =0;
while
(fabs
(r-l)
> eps)
printf
("%.2lf\n"
, mid);}
return0;
}
[牛客]andy的樹被砍了
這種一般就比較簡單吧,一般就是字首和,畢竟是字首和,也沒有負數,單調性很明顯,然後用二分的話可能**就會簡化一點,時間複雜度低一點。感覺可用可不用。我看好像都沒用二分就過了。
#include
#include
#include
using
namespace std;
const
int maxn =
1e5+5;
long
long c[maxn]
;int h[maxn]
;int
main()
cout << endl;
return0;
}
emmm,比暴力的**更簡潔一點。
有些題目要特別巧妙的使用字首和,可以大量的減少時間複雜度:[牛客]transform,而且確定邊界的時候一定要好好想想,要不然就一直錯。
#include
#include
using
namespace std;
const
int maxn =
5e5+5;
int n;
long
long t;
int x[maxn]
;long
long a[maxn]
, _sum[maxn]
, _cost[maxn]
;inline
long
long
getrightcost
(int l,
int r)
inline
long
long
getleftcost
(int l,
int r)
bool
check
(long
long _try)
l = r = mid = n;
while
(true
)return
false;}
intmain()
r = _sum[n]
;while
(l <= r)
printf
("%lld\n"
, r)
;return0;
}
一般我們習慣性的對所求答案進行二分,比如:[牛客]接機
一般的都是乙個模板:
while
(l < r)
重點在於根據題目怎麼寫這個check函式,還有就是對於邊界的判斷,要想好,哪乙個是可行解,應該保留哪乙個邊界。
#include
#include
using
namespace std;
const
int maxn =
1e5+5;
int _time[maxn]
;inline
bool
check
(int n,
int m,
int c,
int mid)
return cnt <= m;
}int
main()
printf
("%d\n"
, r)
;return0;
}
還有一種比較不容易出錯的寫法:
while
(l <= r)
這樣把最後求得的可行解儲存在乙個變數裡面,就可以不用邊界是否正確,最後的解一定是可行的。
剛開始,沒做多少題目,日後再更~
二分 折半 查詢
折半查詢 又叫二分查詢,採用分治思想,適用於不經常變動且查詢頻繁的表 演算法思想 將n個元素 假設n個元素公升序 分為大致相同的兩部分,取data n 2 與目標元素m比較 若data n 2 m return n 2 若data n 2 m 則我們只要在data的左半部分繼續查詢 若data n ...
二分 折半 查詢
二分查詢 請對乙個有序陣列進行二分查詢 輸入乙個數看看該陣列是否存在此數,並且求出下 標,如果沒有就提示 沒有這個數 二分查詢演算法的思路 二分 折半 查詢條件 有序陣列。public class binarysearch 不考慮有重複元素的查詢。int index solutionsearch a...
二分折半排序
板子 插入後,每次與中間值相比較,再與左半部分中間值比較,再與右半部份中間值比較,直到找到它自己的位置,待排序資料 2,1,6,7,4 資料部分 原文 取第乙個元素作為有序表,剩餘的元素作為無序表 其中有序表 2 無序表 1,6,7,4 第一次比較,從無序表中取出第乙個數 1,與中間值2比較,1 2...