数据结构总结之二分
来源:互联网 发布:淘宝达人怎么获得佣金 编辑:程序博客网 时间:2024/04/30 01:14
1.找惟一的一个与x相等的元素的位置
int search(int *arr, int n, int key){ int left = 0, right = n-1; while(left<=right) { int mid = left + ((right - left) >> 1);//防止溢出 if (arr[mid] == key) return mid; else if(arr[mid] > key) right = mid - 1; else left = mid + 1; } return -1;}
2.找第一个与x相等的元素位置
int searchFirstEqual(int *arr, int n, int key){ int left = 0, right = n-1; while(left < right) { int mid = (left+right)/2; if(arr[mid] > key) right = mid - 1; else if(arr[mid] < key) left = mid + 1; else right=mid; } if(arr[left] == key) return left; return -1;}
3.找到最后一个与x相等的元素位置
int searchLastEqual(int *arr, int n, int key){ int left = 0, right = n-1; while(left<right-1) { int mid = (left+right)/2; if(arr[mid] > key) right = mid - 1; else if(arr[mid] < key) left = mid + 1; else left=mid; } if( arr[left]<=key && arr[right] == key) return right; if( arr[left] == key && arr[right] > key) return left; return -1;}
4.找到第一个大于等于x的元素位置
int searchFirstEqualOrLarger(int *arr, int n, int key){ int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] >= key) right = mid-1; else if (arr[mid] < key) left = mid+1; } return left;}
5.找到第一个大于x的元素位置
int searchFirstLarger(int *arr, int n, int key){ int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] > key) right = mid-1; else if (arr[mid] <= key) left = mid+1; } return left;}
6.找到最后一个小于等于x的元素位置
int searchLastEqualOrSmaller(int *arr, int n, int key){ int left=0, right=n-1; while(left<=right) { int m = (left+right)/2; if(arr[m] > key) right = m-1; else if (arr[m] <= key) left = m+1; } return right;}
7.找最后一个小于x的元素位置
int searchLastSmaller(int *arr, int n, int key){ int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] >= key) right = mid-1; else if (arr[mid] < key) left = mid+1; } return right;}
8.要用二分,首先要构造一个单调性的数组,比如这题(当然也有其他方法)
uva10706
构造的s[i]数组代表112123123412345123456123……i的i所在的位置。
#include<iostream>#include<string>#include <stdio.h>#include <stack>using namespace std;long long s[100000];long long n,i;int f(int x){ if(x==1) return 1; long long cnt=s[x-1]-s[x-2]; while(x) { x/=10; cnt++; } return cnt;}int Bsearch(int x){ int h=i; int l=1; while(h>=l) { int mid=(h+l)/2; if(s[mid]>=x) h=mid-1; else l=mid+1; } return l;}int out_result(int pos){ int cnt=n-s[pos-1]; for(int i=1;i<=pos;i++) { int tmp=i; stack<int> s;//这里用栈得到了一个数的第一个第二个……第i个数字 while(tmp) { s.push(tmp%10); tmp/=10; } while(!s.empty()) { int ans=s.top();s.pop(); if(--cnt==0) return ans; } }}int main(){ for(i=1;s[i-1]<= 2147483647;i++) { s[i]=s[i-1]+f(i); } int t;cin>>t; while(t--) { scanf("%d",&n); int pos=Bsearch(n); printf("%d\n",out_result(pos)); } return 0;}
9.我们在构造数组的时候,要注意数组不能太大,怎么解决这个问题呢?——移项。例如:hdu4282
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const __int64 maxn=1<<16;__int64 k;__int64 a[maxn][32];const __int64 MAX=2147483648;//1<<31必须这样写……void init(){ memset(a,0,sizeof(a)); for(int i=1;i<maxn;i++) a[i][1]=i; for(int i=1;i<maxn;i++) for(int j=2;j<32;j++) { a[i][j]=a[i][j-1]*i; if(a[i][j]>=MAX) { a[i][j]=0; break; } }}bool f(__int64 sum,__int64 e,__int64 x){ __int64 l,h,mid; l=x+1; h=maxn; while(l<=h) { mid=(h+l)/2; if(a[mid][e]==0) { h=mid-1; continue; } __int64 tmp=a[mid][e]+e*mid*x; if(tmp==sum) return true; else if(tmp>sum) h=mid-1; else l=mid+1; } return false;}int main(){ init();//设置乘方表,大于等于2的31次方的都为0 while(~scanf("%I64d",&k) && k) { __int64 ans=0; __int64 sum=0; __int64 e; for(__int64 x=1;x<maxn;x++) for(e=2;e<32;e++) { if(a[x][e]==0) break; sum=k-a[x][e]; if(sum<=0) break; if(f(sum,e,x)) ans++; } printf("%I64d\n",ans); } return 0;}
一开始,我构造的数组是x^z+y^z+x*y*z.也就是用三层循环构造数组,结果爆内存。我们可以这样:输入一个k,循环z和x,这样对于每一个z和x,构造的数组就是y^z+x*y*z,然后找与k-x^z相等的y,找到了答案就+1.
10.如果题目让求满足某一条件的最小值,也是用二分法的,比如uva11413
#include <iostream>#include <cstdio>#include <cstring>using namespace std;int v[1001];int n,m;int container_num(int size){ int sum=0; int count=0; for(int i=0;i<n;i++) { if(sum+v[i]>size) { sum=v[i];//当“够了”sum立即变成下一个的sum,然后次数+1 count++; } else sum+=v[i]; } return count+1;}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { int max=0; int sum=0; for(int i=0;i<n;i++) { scanf("%d",&v[i]); sum+=v[i]; if(max<v[i]) max=v[i]; } int l=max; int h=sum; int mid; while(l<h) { mid=(l+h)/2; if(container_num(mid)<=m) h=mid;//仔细想想为什么不是mid-1? else l=mid+1; }; printf("%d\n",l); }}
11.还要注意的有二分法只能对于int型,二分上限下限也要找对。如:uva11516
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;int loc[100005];int n,m;bool f(int mid){ int start=loc[0]; int need=1; for(int i=0; i<m; i++) if(loc[i]>start+mid) { need++; start=loc[i]; } if(need>n) return false; else return true;}int main(){ int t; cin>>t; while(t--) { scanf("%d%d",&n,&m); for(int i=0; i<m; i++) scanf("%d",&loc[i]); sort(loc,loc+m); int hi,lo,mid; hi=(loc[m-1]-loc[0])*2; lo=0; while(hi>lo) { mid=(hi+lo)/2; if(!f(mid))//因为位置都是int,所以直径也是int型,故可以二分 lo=mid+1; else hi=mid; } printf("%.1f\n",lo/2.0); } return 0;}
阅读全文
0 0
- 数据结构总结之二分
- 数据结构之二分搜索
- 数据结构之二分查找
- 数据结构之二分查找
- 数据结构之二分查找法
- 数据结构之二分查找树
- 数据结构之二分查找树
- [数据结构]之调研总结
- 数据结构之查找总结
- 【数据结构之宏观总结 】
- 数据结构总结之map
- 数据结构总结之dfs
- 数据结构总结之队列
- 数据结构总结之bfs
- 数据结构总结之树
- 数据结构总结之KMP
- 数据结构总结之lca
- 数据结构方法之二分查找法
- HDU
- [Unity插件]Bug提交报告插件
- Ctype函数的认识
- hadoop环境搭建和基本测试
- Linux安装mysql数据库
- 数据结构总结之二分
- php笔记
- 深度学习正则化之dropout
- git常用命令
- 浅析Android的资源打包及安装后Apk文件的路径
- Shrio的filterChainDefinitions过滤器配置
- Couldn't resolve resource @drawable/homebackground
- sublime text3破解版 永久注册码安装 配置教程 主题 插件各种满足
- Bandicam 3.3.2.1195版破解及注册机(百度云)