二分题目及其总结.
1.银行贷款
题目传送门:P1163
思路:找到函数单调性,进行二分查找。下面是分析。
#include<bits/stdc++.h>
using namespace std;
double n,m;
int k;
bool find(double x){
return (pow(1.0/(1.0+x),k)>=1-(n/m)*x);//如果大于 向左查找,反之向右查找
}
int main(){
cin>>n>>m>>k;
double l=0,r=10;
while(r-l>=1e-4){ //二分
double mid=(l+r)/2;
if(find(mid)) r=mid;
else l=mid;
}
printf("%.1lf\n",l*100);
return 0;
}
2.烦恼的高考志愿
题目传送门:P1678
本题的二分查找是直接用STL的lower_bound函数实现的。
主要思路是:对学校的分数进行从小到大排序,然后边输入边查找最小值求和就行 时间复杂度 O(nlogm) 时间ok。下面上代码。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],m,n,ans;
int main(){
cin>>m>>n;
for(int i=1;i<=m;i++)
cin>>a[i];
sort(a+1,a+m+1);//排序来时间二分查找
for(int i=1,x;i<=n;i++)
{
cin>>x;
int p=lower_bound(a+1,a+m+1,x)-a;//返回查找的位置
if(p==1) ans+=abs(a[1]-x);//分三种情况 处在第一个 或最后一个 直接取差值
else if(p!=m+1)
ans+=min(abs(a[p]-x),abs(a[p-1]-x));//取前后两个较小的值.
else ans+=abs(a[m]-x);
}
cout<<ans<<endl;
return 0;
}
3.眼红的Medusa
题目传送门:P1571
我做了三种做法实质一样:法1.利用map映射对数字进行标记。法2.两个数组 + STL lower_bound 法3.两个数组排序+自己写一个 二分查找函数。PS(还是STL map好用)
法1.利用map映射对数字进行标记
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int m,n,a[N];
int main(){
cin>>n>>m;
map<int,int>mp;
for(int i=1,x;i<=n;i++)
cin>>a[i];
for(int i=1,x;i<=m;i++)
{
cin>>x;
mp[x]=1;
}
for(int i=1;i<=n;i++)
if(mp[a[i]]) printf("%d ",a[i]);
puts("");
return 0;
}
法2:两个数组 + STL lower_bound
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],b[N],n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
cin>>b[i];
sort(b+1,b+m+1);
for(int i=1;i<=n;i++)
{
int p=lower_bound(b+1,b+m+1,a[i])-b;
if(b[p]==a[i])
printf("%d ",a[i]);
}
puts("");
return 0;
}
法3:自己写二分
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],b[N],n,m;
bool fun(int i){
int l=1,r=m;
while(l<=r)
{
int mid=(l+r)/2;
if(a[i]==b[mid]) return 1;
else if(l==r) return 0;//如果二分到结束还没有找到 返回0
else if(a[i]>b[mid]) l=mid+1;
else if(a[i]<b[mid]) r=mid-1;
}
return 0;//如果跳出循环也没找到 返回0
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
cin>>b[i];
sort(b+1,b+m+1);
for(int i=1;i<=n;i++)
if(fun(i)) printf("%d ",a[i]);
return 0;
}