二分答案
一.求最小值的最大值
例题1 洛谷P2678 跳石头
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll lll,n,m;
ll dis[50005];
ll f(ll down)
{
dis[0]=0;
dis[n+1]=lll;
ll cnt=0;
ll last=0;
for(int i=1;i<=n+1;i++)
{
if(dis[i]-last<down)
{
cnt++;
}
else last=dis[i];
}
return cnt;
}
ll find2()
{
ll l=0;
ll r=lll;
while(l<r)
{
ll mid=(r+l+1)/2;
if(f(mid)<=m) l=mid;
else r=mid-1;
}
return l;
}
int main()
{
cin>>lll>>n>>m;
for(int i=1;i<=n;i++) cin>>dis[i];
cout<<find2()<<endl;
return 0;
}
例题2 洛谷P2855 奶牛跳房子
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int L,n,m;
const int N=5e4+5;
int a[N];
bool check(int x)
{
int pos=0;
int cnt=0;
for(int i=1;i<=n+1;i++)
{
if(a[i]-a[pos]<x) cnt++;
else pos=i;
}
//if(pos!=n+1) return false;
if(cnt>m) return false;
else return true;
}
int find(int k)
{
int l=1,r=L;
while(l<r)
{
int mid=(l+r+1)>>1;
//cout<<check(mid)<<endl;
if(check(mid)) l=mid;
else r=mid-1;
}
return l;
}
signed main()
{
cin>>L>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
a[n+1]=L;
cout<<find(m)<<endl;
return 0;
}
二.求最大值的最小值
例题1 洛谷P1182 数列分段
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100005];
int n,m;
int f(ll up)
{
ll sum=0;
int cnt=1;
for(int i=1;i<=n;i++)
{
if(a[i]>up) return -1;
if(sum+a[i]<=up) sum+=a[i];
else sum=a[i],cnt++;
}
return cnt;
}
int find1()
{
ll l=*max_element(a+1,a+n+1);
ll r=0;
for(int i=1;i<=n;i++) r+=a[i];
while(l<r)
{
ll mid=(l+r)/2;
if(f(mid)<=m) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
cout<<find1()<<endl;
return 0;
}
例题2 洛谷P1396 营救
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e4+5;
int head[N],e[N],w[N],ne[N],idx=0;
bool vis[N];
int n,m,s,t;
void add(int a,int b,int c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=head[a];
head[a]=idx++;
}
bool flag=false;
/*
void dfs(int s,int t,int x)
{
//cout<<1<<endl;
vis[s]=true;
if(flag) return ;
if(s==t)
{
flag=true;
return ;
}
for(int i=head[s];i!=-1;i=ne[i])
{
int ta=e[i];
if(!vis[ta])
{
if(w[i]<=x) dfs(ta,t,x);
if(flag) return ;
vis[ta]=false;
}
}
}
*/
queue<int> q;
bool bfs(int s,int t,int x)
{
while(q.size()) q.pop();
memset(vis,false,sizeof(vis));
q.push(s);
while(q.size())
{
int pos=q.front();
q.pop();
if(pos==t) return true;
if(vis[pos]) continue;
vis[pos]=true;
for(int i=head[pos];i!=-1;i=ne[i])
{
int ta=e[i];
if(!vis[ta])
{
if(w[i]>x) continue;
else q.push(ta);
}
}
}
return false;
}
bool f(int s,int t,int x)
{
memset(vis,false,sizeof(vis));
//flag=false;
//dfs(s,t,x);
//return flag;
return bfs(s,t,x);
}
int find()
{
int l=0,r=1e4+5;
while(l<r)
{
int mid=(l+r)>>1;
//cout<<f(s,t,mid)<<endl;
if(f(s,t,mid)) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin>>n>>m>>s>>t;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
cout<<find()<<endl;
return 0;
}
三.求满足条件的最小值
例题1 洛谷P1638 逛画展
转化->求满足能看到所有画师的画所需的最小值
代码
/*#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-8;
double l[N];
int n,k;
bool check(double x)
{
int cnt=0;
for(int i=1;i<=n;i++) cnt+=floor(l[i]/x);
if(cnt>=k) return true;
else return false;
}
double find1()
{
double ll=0.0;
double r=0.0;
for(int i=1;i<=n;i++) r=max(l[i],r);
while(r-ll>eps)
{
double mid=(ll+r)/2.0;
if(check(mid)) ll=mid;
else r=mid;
}
return ll;
}
char res[100];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>l[i];
double ans=find1();
sprintf(res,"%.3lf",ans);
res[strlen(res+1)]='\0';
printf("%s",res);
return 0;
}
*/
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N];
int resl,resr;
int vis[N];
bool check(int x)
{
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1;i<=x;i++)
{
if(vis[a[i]]==0) cnt++;
vis[a[i]]++;
}
if(cnt>=m)
{
resl=1,resr=x;
return true;
}
for(int i=x+1;i<=n;i++)
{
vis[a[i-x]]--;
if(vis[a[i-x]]==0) cnt--;
if(vis[a[i]]==0) cnt++;
vis[a[i]]++;
if(cnt>=m)
{
resl=i-x+1,resr=i;
return true;
}
}
return false;
}
int find1()
{
int l=0,r=1e6+5;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
return l;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
find1();
cout<<resl<<" "<<resr<<endl;
}
int main()
{
solve();
return 0;
}
例题2 洛谷P4058 木材
代码
#include<bits/stdc++.h>
#define int ull
//#define int long long
using namespace std;
typedef unsigned long long ull;
const int N=2e5+5,inf=0x3f3f3f3f;
int n,s,ll;
int h[N],a[N];
int lh[N];
bool check(int x)
{
int cnt=0;
int sum=0;
for(int i=1;i<=n;i++) lh[i]=h[i];
int tmp=0;
for(int j=1; j<=n; j++)
{
if(lh[j]+x*a[j]>=ll) tmp+=lh[j]+x*a[j];
//lh[j]+=a[j];
if(tmp>=s) return true;
}
return false;
}
int find2()
{
int l=0,r=1e18;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
return l;
}
signed main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin>>n>>s>>ll;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++) cin>>a[i];
cout<<find2()<<endl;
return 0;
}
四.求满足条件的最大值
例题1 洛谷P1577 切绳子
注意
本题最后要求的不是四舍五入,而是直接保留。最后三行很重要
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-8;
double l[N];
int n,k;
bool check(double x)
{
int cnt=0;
for(int i=1;i<=n;i++) cnt+=floor(l[i]/x);
if(cnt>=k) return true;
else return false;
}
double find1()
{
double ll=0.0;
double r=0.0;
for(int i=1;i<=n;i++) r=max(l[i],r);
while(r-ll>eps)
{
double mid=(ll+r)/2.0;
if(check(mid)) ll=mid;
else r=mid;
}
return ll;
}
char res[100];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>l[i];
double ans=find1();
sprintf(res,"%.3lf",ans);
res[strlen(res+1)]='\0';
printf("%s",res);
return 0;
}
例题2 洛谷P2440 木材加工
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int len[N];
int n,k;
bool check(int x)
{
int res=0;
for(int i=1;i<=n;i++) res+=len[i]/x;
return res>=k;
}
int find2()
{
int l=0;
int r=1e8+1;
//for(int i=1;i<=n;i++) r=max(r,len[i]);
while(l<r)
{
int mid=(l+r+1)>>1;
//cout<<f(mid)<<endl;
if(check(mid)) l=mid;
else r=mid-1;
}
return l;
}
signed main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>len[i];
cout<<find2()<<endl;
return 0;
}
例题3 洛谷P2920 Time Management S
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
struct node_
{
int t,s;
friend bool operator < (const node_ x,const node_ y)
{
return x.s<y.s;
}
}node[N];
int n,maxn;
bool check(int x)
{
for(int i=1;i<=n;i++)
{
x+=node[i].t;
if(x>node[i].s) return false;
}
return true;
}
int find()
{
int l=-1e5,r=1e5;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
return l;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>node[i].t>>node[i].s;
maxn=max(node[i].s,maxn);
}
sort(node+1,node+n+1);
int res=find();
if(res<0||res>=maxn) cout<<"-1"<<endl;
else cout<<res<<endl;
}