二分搜索
Posted xwww666666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分搜索相关的知识,希望对你有一定的参考价值。
模板
找出最左边的一个,最右边的一个,和长度
注意找左位置时要判断:
1>不可以是字串结尾,不然为0或为空
2>不可以不等于key
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int n,m; const int N=100003; int d[N]; int main() scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&d[i]); int x; while(m--) scanf("%d",&x); int pos1=lower_bound(d+1,d+n+1,x)-d; if(pos1>n || d[pos1]!=x) printf("-1 -1 -1\n"); continue; int pos2=upper_bound(d+pos1+1,d+n+1,x)-d; printf("%d %d %d\n",pos1,pos2-1,pos2-pos1); return 0;
例题1
阿弥陀佛数数游戏
N个数字(N<=500000),K(K<=500000)个问题,
每个问题询问从L到R中,到底有多少个数字是KEY值?
数据都是int可以存储的
神仙思路:
题目虽然有两个关键字,但是只求第一个关键字相等的情况,所以可以直接sort
sort以后找到相等区间,再去搞第二关键字就好
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int n,k; const int N=500003; struct node int v,id; bool operator < (const node & o) const return v==o.v? id<o.id :v<o.v; d[N]; int main() scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&d[i].v ),d[i].id =i; sort(d+1,d+n+1); int l,r; node t; while(k--) scanf("%d%d%d",&l,&r,&t.v ); t.id =l; int pos1=lower_bound(d+1,d+n+1,t)-d; if(pos1>n || d[pos1].v !=t.v || d[pos1].id >r) printf("0\n"); else t.id =r; int pos2=upper_bound(d+pos1,d+n+1,t)-d; printf("%d\n",pos2-pos1); return 0;
例题2
晒衣服
1>贪心
众所周知,堆比sort快(除了我)
#include<cstdio> #include<cstdlib> #include<queue> using namespace std; priority_queue <int> q; int n,a,b; int main() scanf("%d%d%d",&n,&a,&b); int x; for(int i=1;i<=n;i++) scanf("%d",&x),q.push(x); int t=0; while(q.top() > a*t) x=q.top() -b; q.pop() ; t++; q.push(x); printf("%d\n",t); return 0;
2>二分搜索答案
二分快速确认答案范围
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n,a,b; const int N=500000; int d[N+3]; bool check(int tm) int cnt=tm; for(int i=n;i;i--) if(d[i]<=tm*a) return true; int t=d[i]-tm*a; int nd=(ceil(t/(b*1.0))); if(nd>cnt) return false; else cnt-=nd; return true; int main() scanf("%d%d%d",&n,&a,&b); for(int i=1;i<=n;i++) scanf("%d",&d[i]); sort(d+1,d+n+1); int l=1,r=d[n]/a+1; while(l<r) int mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; printf("%d\n",l); return 0;
例题3
有道搜索框
//注意呀:字符串可以都看作数 //只是比大小是左对齐形式罢了 #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; int n,q; const int N=10003; string s[N],ask; int pos; int main() cin>>n;//cin和scanf不要混用 for(int i=0;i<n;i++) cin>>s[i]; sort(s,s+n); n=unique(s,s+n)-s;//神仙去重 cin>>q; while(q--) cin>>ask; int pos1=lower_bound(s,s+n,ask)-s; pos=ask.length() ; ask[pos-1]++; int pos2=lower_bound(s+pos1,s+n,ask)-s; if(pos1==pos2)//神仙判ask是否为s[pos1]的前缀 ask[pos-1]--; cout<<ask<<endl; else for(int i=0;i<8 && pos1+i<pos2;i++) cout<<s[pos1+i]<<" "; cout<<endl; return 0;
#include<cstdio> #include<cstdlib> #include<queue> using namespace std; //众所周知,堆比sort快 priority_queue <int> q; int n,a,b; int main() scanf("%d%d%d",&n,&a,&b); int x; for(int i=1;i<=n;i++) scanf("%d",&x),q.push(x); int t=0; while(q.top() > a*t) x=q.top() -b; q.pop() ; t++; q.push(x); printf("%d\n",t); return 0;
以上是关于二分搜索的主要内容,如果未能解决你的问题,请参考以下文章