不务正业-二分基础
来源:互联网 发布:贝尔.格里尔斯 知乎 编辑:程序博客网 时间:2024/05/17 06:20
二分作为查找利器很实用:
本篇主要讲述二分理论
二分解题
二分STL解题
二分模板
非递推版本
int search(int x) //二分查找{ int left=1,right=n; while(left<=right) //注意这里必须等于 { int mid=(left+right)/2; if(x>num[mid]) left=mid+1; else if(x==num[mid]) { return mid; } else right=mid-1; }}题目:
01:查找最接近的元素
//二分查找模板#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int maxn = 100001;long long int num[maxn];int n;int search(int key) //二分查找{ int left=1,right=n; int ans; while(left<=right-2) //注意这里必须等于 { int mid=(left+right)/2; if(key>num[mid]) left=mid; else right=mid; } if(fabs(num[left]-key)<=fabs(num[left+1]-key)&&left<n) ans = num[left]; else { ans = num[left+1]; } return ans;}int main(){ //int n; long long int m; long long int tar; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",&num[i]); } scanf("%lld",&m); while(m--) { scanf("%lld",&tar); cout<<search(tar)<<endl;; } return 0;}
07:和为给定数
#include <stdio.h>#include <stdlib.h>#include <algorithm>using namespace std;int n;int a[100002];int m;int search(int x){ int l = x+1; int r = n; while(l<=r) { int mid = (l+r)/2; if(a[mid]==m-a[x]) return mid; else if(a[mid]>m-a[x]) r = mid-1; else l = mid+1; } return -1;}int main(){ int tmp; int i,l; int r,mid; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1);//选出小的更小 scanf("%d",&m); for(i=1;i<=n;i++) { tmp = search(i); if(a[tmp]==m-a[i])//输出结果 { printf("%d %d\n",a[i],m-a[i]); return 0; } } printf("No\n");//没有 return 0;}
06:月度开销
题目是要求得开销最小的月度划分的最大开销,不难看出在极端情况(如 每天开销为1,1,50,划分为2个fajo月)时开销最小值是每天开销的最大值(50)。因此,我们可以在读入时找到每天开销的最大值,作为二分查找中的左边界(left)。但是右边界(right)在本题目中并不好找,我们只能尽量将它设大一些,此时列举极端情况(如 每天开销为4,5,6,划分为1个fajo月),则发现最小开销为每天开销的总和。于是我们可以把每天开销的和(sum)作为右边界使用。
接下来是二分查找,此时的mid是作为假定的最小划分的最大开销使用。然后我们需要判断mid是否成立。
判断的方法如下:
尝试在每一天的开销中划分,若该fajo月的开销总额没有超过mid,就继续累加;否则将划分出的fajo月总数加1,并重新累加下一个fajo月。在中途若发现该fajo月的开销已经比mid大,就说明mid是错误(false)的。划分完毕后,比较划分出的fajo月总数和m(要求划分出的fajo月总数),若比m大(严格”>”),说明mid不正确;反之正确。
最后需要改变左右边界值。根据之前判断的结果,若正确,根据题意,要找到最小的划分,所以向下查找(改变right的值);反之,说明mid太小,就向上查找(改变left的值)。
//月份中最大的花费作为左端点,总花费作为右端点进行二分#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 100009;int n,m,maxx,right1,ans;int a[maxn];int check(int x){ int sum = 0; int yfen = 1; for(int i=1;i<=n;i++) { if(sum+a[i]<=x) { sum+=a[i]; } else { sum = a[i]; yfen++; if(sum>x) return 0; } } if(yfen<=m) return 1; else return 0;}int search(){ int l = maxx; int r = right1; int mid; while(l<=r) { mid = (l+r)/2; if(check(mid)) { ans = mid; r = mid-1; } else l = mid+1; } return ans;}int main(){ cin>>n>>m; right1 = 0; for(int i=1;i<=n;i++) { cin>>a[i]; right1+=a[i]; if(a[i]>maxx) maxx = a[i]; } cout<<search()<<endl; return 0;}
10:河中跳房子
左端点为0,右端点为总长度,二分,
根据i,j之间的距离来决定拆除的石板数,依次枚举
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 50020;int river[maxn];int L,l,r,n,m;int mid;int ans;int search(int mid){ int cnt = 0,wz = 0; for(int i=1;i<=n;i++) { if(river[i]-river[wz]<=mid) { cnt++; } else wz = i; } return cnt;}int main(){ scanf("%d%d%d",&L,&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&river[i]); } n++; river[n] = L; l = 0; r = L; while(l<=r) { int mid = (l+r)/2; ans = search(mid); //cout<<ans<<endl; if(ans>m) r = mid-1; else l = mid+1; } cout<<l<<endl; return 0;}
二分查找模板 nyoj626
#include <iostream>#include <algorithm>#include <cstdio>using namespace std;const int maxn = 50001;int a[maxn],b[maxn];int n,m;int search(int key,int* vec,int len){ int l = 0; int r = len-1; while(l<=r) //注意这里必须等于 { int mid=(l+r)/2; if(key>vec[mid]) l=mid+1; else if(key==vec[mid]) { return 1; } else r=mid-1; } return 0;}int main(){ int m,n,count; while(~scanf("%d%d",&m,&n)) { count=0; if(n==0&&m==0) break; for(int i=0;i<m;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); if(m>=n) { sort(a,a+m); for(int i=0;i<n;i++) { if(search(b[i],a,m)) count++; } printf("%d\n",count); } else { sort(b,b+n); for(int i=0;i<m;i++) { if(search(a[i],b,n)) count++; } printf("%d\n",count); } } return 0;}
阅读全文
1 0
- 不务正业-二分基础
- “不务正业”
- 不务正业
- 小米手机被指不务正业:基础功能弱 刷机成主业
- 乱七八糟,不务正业
- 不务正业-搜索
- 基础二分
- 二分基础
- 【二分】基础
- Goof around 不务正业
- acm是不务正业?
- R不务正业之RCurl
- acm是不务正业?
- R不务正业之RCurl
- R不务正业之RCurl
- 那些“不务正业”的软件.......
- 基础...二分搜索
- 二分图基础
- dc_shell教程
- FastJsonUtil
- CryptoJS简单使用
- <9/24>集训周记
- EventBus源码分析
- 不务正业-二分基础
- 《Focusing Attention:Towards Accurate Text Recognition in Natural Images》阅读
- 【问题记录】使用fregment实现底部菜单,旋转屏幕时,fregment会增加
- 使用eclipse搭建ssh框架
- HTML学习笔记五 列表标签+表格标签
- 记录各个网站cookie的含义。
- matlab操作快捷键
- Android多点触控技术实战,自由地对图片进行缩放和移动
- ubuntu怎么连接宽带,无法联网的简单便捷的解决方法