二分算是比較高效的算法,分爲二分查找和二分答案
二分查找
在排好序的數組中查找所需元素的位置,單次查找複雜度(log2n)
思想就是比較自己的值和中間值的大小,比mid大就向右區間二分,比mid小就向左區間二分,直到自己的值和左端點的值相等。
代碼
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n; int k=0;
struct node{
int mark,ball;
}a[100001];
int cmp(node x,node y)
{
return x.ball<y.ball;
}
int erfen(int l,int r)
{
while(l<=r)
{
int mid=(l+r)/2;
if(k>a[mid].ball) l=mid+1;
else r=mid-1;
}
if(a[l].ball==k) cout<<a[l].mark<<endl;
else cout<<"0"<<endl;
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>a[i].ball;
a[i].mark=i;
}
sort(a+1,a+n+1,cmp);
int q;cin>>q;
for(int i=1;i<=q;++i)
{
k=0;
cin>>k;
erfen(1,n);
}
return 0;
}
二分答案
根據答案可以推出答案是否合理,一般題目關鍵字爲最大值的最小或最小值的最大,每次判斷二分的結果是否可以,如果可以存儲並繼續找更優的解,不可以就退一步找可以的解。
代碼
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,a[100001],mid;
int maxx=0,all=0,ans;
bool judge(int x)
{ int k=0,cnt=1;
for(int i=1;i<=n;++i)
{ k+=a[i];
if(k>x)
{
cnt++;
k=a[i];
}
}
if(cnt>m) return 0;
else return 1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i)
{
cin>>a[i];
if(a[i]>maxx) maxx=a[i];
all+=a[i];
}
int l=maxx,r=all;
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid)==1)
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
cout<<ans;
return 0;
}