二分答案
0.定義
二分搜索法,是通過不斷縮小解可能存在的范圍,從而求得問題最優解的方法。
1.查找值
在一個有序的數組中查找一個值。
因為有序,所以可以二分。
這里就找了自己十幾天前打的一個求有序序列的上界的代碼。
大致是這樣的:取出中間的數,如果大于要查找的值,答案就在左邊,否則在右邊。這樣每次查找都可以把范圍縮小一半。所以時間復雜度就是O(log n)了。
2.最大化最小值
顧名思義,就是通過二分答案讓最小值最大。好吧我承認這是句廢話
如果中間值滿足題意,那么最小值大于等于中間值。否則小于中間值。
3.最小化最大值
類似上文。
int BS() {int lb=0,ub=INF;while(lb+1<ub){int mid=(lb+ub)/2;if(check(mid)) ub=mid;else lb=mid;}return ub; }4.最大化平均值
給定n個物品,有自己的重量和價值。選出k個物品,使平均價值最大。
雖然有些并不一定是二分但有些也確實是二分。到時候再確定是不是二分。
這里就把用二分做的題目所用的方法推導一下好了。
定義C(x):=可以選擇使得單位重量的價值不小于x。
若C(x)可行,則
則 ∑i=1kv[i]??x?∑i=1kw[i]?≥0∑i=1kv[i]?x?∑i=1kw[i]≥0
∑i=1kv[i]??∑i=1kx?w[i]?≥0∑i=1kv[i]?∑i=1kx?w[i]≥0
∑i=1kv[i]?k?w[i]?≥0∑i=1kv[i]?k?w[i]≥0
所以就可以用這個思路來二分答案了。 bool cmp(node p,node q) { return p.t>q.t; } bool check(double x) {for(int i=1;i<=n;i++) a[i].t=a[i].a-a[i].b*x;sort(a+1,a+n+1,cmp);double ans=0;for(int i=1;i<=n-k;i++) ans+=a[i].t;return ans>=0; } double BS() {double lb=0.0,ub=1.0;while(lb+eps<ub){double mid=(lb+ub)/2;if(check(mid)) lb=mid;else ub=mid;}return lb; }
5.其他的一些
有可能二分的不是明顯地表示上面的某個模型,這時候就要推導一發。(也有可能就不是上面的某個模型?)
是不是二分要理智判斷。似乎又是一句廢話。問題的解一般要單調。
有時候還會有一些惡心的二分套二分什么的。
總結
- 上一篇: 温湿度传感器——DHT11学习总结
- 下一篇: Apache shiro反序列化(CVE