目录
1. HYSBZ - 1734 Aggressive cows 愤怒的牛
一. 二分实现
1. 内置函数
(1)lower_bound()
(2)upper_bound()
(3)binary_search()
2. 手写二分
int i = 0,j = n;
while(i<=n){
int m = i + (j - i)/2;
if(judge(m))i = m+1;//要执行的操作
else j = m-1;
}
注意不要把二分只限于三种函数,手写二分更适用,二分查找是一种思想。
二. 例题分析
1. HYSBZ - 1734 Aggressive cows 愤怒的牛
Problem Description
农夫 John 建造了一座很长的畜栏,它包括NN (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000). 但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢
使最小最大(想到二分),可以二分枚举距离 , 判断该距离是否合适。要是所有隔间间距离都大于等于这个距离,那么可能有比这个距离还大的最小距离,继续把起点选为该点继续二分。否则把终点选为该点,最大距离只能比这个小了。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000000 + 5;
LL num[maxn];
int n,c;
bool judge(LL len)
{
int lefted = 0,righted = 0;
int tot = 1;
while(lefted<n){
if(tot==c)return true;
while(righted<n&&num[righted] - num[lefted]<len)righted++;
if(righted>=n)return false;
tot++;lefted = righted;
}
return false;
}
int main()
{
scanf("%d%d",&n,&c);
for(int i = 0;i<n;i++)scanf("%lld",&num[i]);
sort(num,num + n);
LL l = 0,r = num[n-1] - num[0];
LL ans = 0;
while(l<=r){
LL mid = l + (r-l)/2;
if(judge(mid)){ans = mid;l = mid + 1;}
else r = mid-1;
}
printf("%lld\n",ans);
return 0;
}
2. UVA - 12124 Assemble
Problem Description
给出n种类型电脑配件,每种给出几个品牌和品牌的价格和质量,要求每种类型配件必须选一个,给出总钱数m,求出在m之下买的最大总质量的组装电脑。注意组装电脑的质量等于所有配件里质量最低的那个。
二分最大质量,每种质量下判断符不符合条件。条件是:所有配件必须选一个 + 总钱数<=m + 所有配件质量>=二分质量。因此可以把每种配件里面所有品牌按照质量有小到大钱数有小到大排序。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
#include<vector>
#include<set>
using namespace std;
const int maxn = 1000 + 5;
struct Node
{
string name;
int price,quality;
bool operator < (const Node &another)const{
if(price==another.price)return quality > another.quality;
return price < another.price;
}
Node (string s,int m,int y):name(s),price(m),quality(y) {}
};
map<string,int> compare;
set<Node> num[maxn];
int n,all;
int k;
bool judge(int x)
{
int tot = all;
for(int i = 0;i<k;i++){
bool sign = false;
for(set<Node>::iterator itr = num[i].begin();itr!=num[i].end();itr++){
if(itr->quality<x)continue;
else if(itr->quality>=x&&tot>=itr->price){
tot-=itr->price;
sign = true;
break;
}
else{
break;
}
}
if(!sign)return false;
}
return true;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&all);
k = 0;
compare.clear();
for(int i = 0;i<n;i++)num[i].clear();
int maxx = -1;
for(int i = 0;i<n;i++){
string type,na;
int p,q;
cin>>type>>na>>p>>q;
if(!compare.count(type))compare[type] = k++;
int w = compare[type];
num[w].insert(Node(na,p,q));
maxx = max(maxx,q);
}
int l = 0,r = maxx;
int ans = 0;
while(l <= r){
int mid = l + (r - l)/2;
if(judge(mid)){ans = mid;l = mid + 1;}
else r = mid - 1;
}
printf("%d\n",ans);
}
return 0;
}