二分搜索及其思想(挑战例题总结)

来源:互联网 发布:网络用语der什么意思 编辑:程序博客网 时间:2024/06/07 05:30
二分搜索的思想中,对临界值的区分比较模糊。。。




首先看了挑战的第一章,额,发现 lb,ub的区分看不懂啊。。。为毛是初始化是-1和n啊???
纠结很久......


然后又看看low_bound和upper_bound函数的源代码。。。。 

lower_bound()

upper_bound()

我感觉书上是那个lb不需要是-1啊(不想纠结了ORZ)


iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值> key的第一个元素。 


upper_bound()-lower_bound()就是相同的个数了2333


low_bound()与upper_bound()区别就是<与<=号的区别。。这个自己手码一次就可以了。。。


贴上自己喜欢的代码


#include<iostream>#include<cstdio>#include<cstring>using namespace std;int num[10];int Low_bound(int *Array,int Size,int key){    int pos;    int first,last,middle;    first=0;    last=Size;    pos=first;    while(first<last)    {        int middle=(first+last)>>1;        if(Array[middle]<key)        {            first=middle+1;            pos=first;        }        else        {            last=middle;            pos=last;        }    }    return pos;}int main(){    for(int i=0;i<5;i++) scanf("%d",&num[i]);    cout<<Low_bound(num,5,2)<<endl;    return 0;}



然后再是二分的思想解决一些问题。。。。。。。。
因为二分查找的效率狠高,所以可以根据二分查找到答案范围。。。
一般跟贪心和数学相关的一些转化。。。。(题目还是做得太少了。等等后来做多了再反思一下)


然后书上的3个例子自己手码一次。再做题目.....


1.假定一个解判断是否可行
2.最大化最小值
3.最大化平均值


1. POJ 1064 Cable master

需要正确的精度姿势。。。。。
1.double最好用cin
2.floor是向下取整函数。。。

精度

代码:

#include <iostream>#include <map>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include<sstream>#include <cmath>using namespace std;#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define INF 1001000#define sq(x) (x)*(x)#define eps (1e-10)#define clr(x) memset((x),0,sizeof (x))#define cp(a,b) memcpy((a),(b),sizeof (b))typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> P;const int maxn=10100;double str[maxn];int N,K;bool c(double len){    int sum=0;    for(int i=0;i<N;i++)    sum+=(int)(str[i]/len);    return  sum>=K;}int main(){    cin>>N>>K;    for(int i=0;i<N;i++) cin>>str[i];    double left,right,mid;    left=0,right=INF;    for(int i=0;i<100;i++)    {        mid=(left+right)/2;        if(c(mid)) left=mid;        else       right=mid;    }    printf("%.2f\n",floor(right*100)/100);    return 0;}

2.最大化最小值

POJ 2456 Aggressive cows

自己代码

#include <iostream>#include <map>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include<sstream>#include <cmath>using namespace std;#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define INF 1e9+10#define sq(x) (x)*(x)#define eps (1e-10)#define clr(x) memset((x),0,sizeof (x))#define cp(a,b) memcpy((a),(b),sizeof (b))typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> P;const int maxn=101000;int cow[maxn];int N,C;bool c(int x){    int num=1;    int last=0;    for(int k=1;k<N;k++)    {        if(cow[k]-cow[last]>=x)        {            last=k;            num++;        }    }    return num>=C;}int main(){    cin>>N>>C;    for(int i=0;i<N;i++) cin>>cow[i];    sort(cow,cow+N);    int left,right,mid;    left=0;    right=INF;    for(int i=0;i<100;i++)    {        mid=(left+right)>>1;        if(c(mid)) left=mid;        else       right=mid;    }    cout<<left<<endl;    return 0;}

书上代码:

#include <iostream>#include <map>#include <algorithm>#include <bitset>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include<sstream>#include <cmath>using namespace std;#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define INF 1e9+100;#define sq(x) (x)*(x)#define eps (1e-10)#define clr(x) memset((x),0,sizeof (x))#define cp(a,b) memcpy((a),(b),sizeof (b))const int maxn=100100;int pos[maxn];int N,C;bool c(int d){    int last,cnt;    last=0;    cnt=1;    for(int i=1;i<C;i++)    {        while(cnt<N&&pos[cnt]-pos[last]<d)        cnt++;        if(cnt==N) return false;        last=cnt++;    }    return true;}int main(){    scanf("%d%d",&N,&C);    for(int i=0;i<N;i++) scanf("%d",&pos[i]);    sort(pos,pos+N);    int lb,ub;    lb=0;    ub=INF;    while(ub-lb>1)    {        int mid=(lb+ub)/2;        if(c(mid)) lb=mid;        else       ub=mid;    }    printf("%d\n",lb);    return 0;}

自己的代码比书上慢了很多,原因是二分的结束条件判断不好。。。。
mark一个...
然后想想 输出是left还是right。。。不要凭印象随便写。。。。看代码,满足是左,不满足是右。。。。所以输出为左,想想就清楚了。。。




最大化平均值
需要一个数学思维转换下。。即可。


恩!OK。开始做题目了、


0 0
原创粉丝点击