整数二分
浮点数二分
注意: < < 1 \color{blue}{注意: <<1 } 注意:<<1只适用于整数
一般为
最大化
查找
一元三次方程求解(1024)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
double a,b,c,d;
double fun(double x){
return a*x*x*x+b*x*x+c*x+d;
}
double mfind(double l,double r){
//区分:浮点数是>
while(r-l>1e-4){
double mid=(l+r)/2;
// 函数零点定理
if(fun(mid)*fun(r)<0) l=mid;//最大化
else r=mid;
}
return l;
}
int main(){
cin>>a>>b>>c>>d;
rep(i,-100,100){
double y1=fun(i),y2=fun(i+1);
if(!y1) printf("%.2lf ",1.0*i);//y1==0,即表示根
//1.0*i:将i转化为double类型
if(fun(i)*fun(i+1)<0) printf("%.2lf ",mfind(i,i+1));
}
return 0;
}
二分答案
1.百搭算法:贪心,DP,搜索,前缀和等
2. 画出函数图像,找出哪里是可行区,返回真
木材加工(2240)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
int n,k,a[N];
bool check(int x){
ll y=0;
rep(i,1,n) y+=a[i]/x;
return y>=k;
}
int find(){
int l=0,r=1e8+10;
while(l+1<r){
int mid=l+r>>1;
if(check(mid)) l=mid;
else r=mid;
}
return l;
}
int main(){
cin>>n>>k;
rep(i,1,n) cin>>a[i];
cout<<find();
return 0;
}
跳石头(2678)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
int n,m,L;
int a[N];
bool check(int x){
int last=0,cnt=0;
rep(i,1,n+1){
if(a[i]-a[last]<x) cnt++;
else last=i;
}
return cnt<=m;
}
int find(){
int l=0,r=1e8+10;
while(l+1<r){
int mid=l+r>>1;
if(check(mid)) l=mid;
else r=mid;
}
return l;
}
int main(){
cin>>L>>n>>m;
rep(i,1,n) cin>>a[i];
a[n+1]=L;
cout<<find();
return 0;
}
聪明的质检员(1314)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
int n,m,w[N],v[N],l[N],r[N];//重量w,价值v
ll s,sn[N],sv[N],ans=1e18;
bool check(int W){
ms(sn,0);
ms(sv,0);
rep(i,1,n){
if(w[i]>=W) sn[i]=sn[i-1]+1,sv[i]=sv[i-1]+v[i];
else sn[i]=sn[i-1],sv[i]=sv[i-1];
}
ll y=0;
rep(i,1,m)
y+=(sn[r[i]]-sn[l[i]-1])*(sv[r[i]]-sv[l[i]-1]);
ans=min(ans,llabs(y-s));//取最优解
return s>=y;
}
ll find(){
int l=0,r=1e6+10;
while(l+1<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid;
}
return ans;
}
int main(){
cin>>n>>m>>s;
rep(i,1,n) cin>>w[i]>>v[i];
rep(i,1,m) cin>>l[i]>>r[i];
cout<<find();
return 0;
}
借教室(1083)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
int n,m,r[N],d[N],s[N],t[N];
ll num[N];//教室需求数
bool check(int x){
ms(num,0);
rep(i,1,x){//ding dan
num[s[i]]+=d[i];
num[t[i]+1]-=d[i];
}
rep(i,1,n){//day
num[i]+=num[i-1];
if(r[i]<num[i]) return 0;
}
return 1;
}
int find(){//ding dan
int l=0,r=m+1;
while(l+1<r){
int mid=l+r>>1;
if(check(mid)) l=mid;
else r=mid;
}
return l;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>m;
rep(i,1,n) cin>>r[i];
rep(i,1,m) cin>>d[i]>>s[i]>>t[i];
if(check(m)){
puts("0");
return 0;
}
cout<<"-1"<<endl<<find()+1;
return 0;
}
刺杀大使(1902 )
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define per(i,x,y) for(int i = x; i >= y; i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e3 + 10, mod = 998244353;
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int n,m,vis[N][N],p[N][N];
bool dfs(int x,int y,int P){
if(x==n) return 1;
vis[x][y]=1;
rep(i,0,3){//attendent!!
int a=x+dx[i],b=y+dy[i];
if(a>=1 && a<=n && b>=1 && b<=m && !vis[a][b] && p[a][b]<=P)
if(dfs(a,b,P))
return 1;
}
return 0;
}
int find(){
int l=-1,r=1e3+10;
while(l+1<r){
int mid=l+r>>1;
ms(vis,0);
if(dfs(1,1,mid)) r=mid;//都是从(1,1)出发
else l=mid;
}
return r;
}
int main(){
cin>>n>>m;
rep(i,1,n)
rep(j,1,m)
cin>>p[i][j];
cout<<find();
return 0;
}
银行贷款(1163 )
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define per(i,x,y) for(int i = x; i >= y; i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;
int a,b,c;
bool check(double x){
double s=a;
rep(i,1,c){
s=(1+x)*s-b;
}
return s>=0;
}
double find(){
double l=0,r=10;
while(r-l>=1e-5){
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
return r;
}
int main(){
cin>>a>>b>>c;
printf("%.1lf",find()*100);
return 0;
}