A06 二分答案

视频链接:A06 二分答案 最好的套路_哔哩哔哩_bilibili

1. Luogu P2440 木材加工

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N = 100005;
int n, k, a[N];

bool check(int x){
  LL y=0; //段数
  for(int i=1;i<=n;i++) y+=a[i]/x;
  return y>=k; //x小,y大
}
int find(){
  int l=0, r=1e8+1;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) l=mid; //最大化
    else r=mid;
  }
  return l; 
}
int main(){
  scanf("%d%d",&n,&k);
  for(int i=1; i<=n; i++)scanf("%d",&a[i]);
  printf("%d\n",find());
  return 0;
}

2. Luogu P2678 [NOIP2015 提高组] 跳石头

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

int L, n, M, a[500005];

bool check(int x){
  int last=0,cnt=0;
  for(int i=1;i<=n+1;i++)
    if(a[i]-a[last]<x) cnt++;//贪心
    else last=i; 
  return cnt<=M; //x小,cnt小
}
int find(){
  int l=0, r=1e9+1;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) l=mid; //最大化
    else r=mid;
  }
  return l;
}
int main(){
  scanf("%d%d%d",&L,&n,&M);
  for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  a[n+1]=L; //右边界
  printf("%d\n",find());
  return 0;
}

3. Luogu P1314 [NOIP2011 提高组] 聪明的质监员

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N=200010;
int n,m, w[N],v[N],l[N],r[N];
LL s,sn[N],sv[N],ans=1e18;

bool check(int W){    
  memset(sn,0,sizeof sn);
  memset(sv,0,sizeof sv);
  for(int i=1;i<=n;i++){ //前缀和
    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;
  for(int i=1;i<=m;i++)
    y+=(sn[r[i]]-sn[l[i]-1])*(sv[r[i]]-sv[l[i]-1]);
  ans=min(ans,llabs(y-s)); //最优解
  return y<=s; //W大,y小
}
LL find(){
  int l=0,r=1e6+1;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) r=mid; //最小化
    else l=mid;
  }
  return ans;
}
int main(){
  scanf("%d %d %lld",&n,&m,&s); 
  for(int i=1;i<=n;i++)
    scanf("%d%d",&w[i],&v[i]);
  for(int i=1;i<=m;i++)
    scanf("%d%d",&l[i],&r[i]);
  printf("%lld",find());
  return 0;
}

4. Luogu P1083 [NOIP2012 提高组] 借教室

#include<iostream>
#include<cstring>
#include<cstdio> 
using namespace std;

const int N = 1000010;
int n,m;
int r[N],d[N],s[N],t[N];
long long num[N]; //每天教室需求数

bool check(int x){
  memset(num,0,sizeof num);
  for(int i=1;i<=x;i++){//枚举订单数
    num[s[i]]+=d[i];
    num[t[i]+1]-=d[i]; //差分
  }
  for(int i=1;i<=n;i++){//枚举天数
    num[i]+=num[i-1]; //前缀和
    if(num[i]>r[i])return false;
  }
  return true; //x小,true
}
int find(){
  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(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)
    scanf("%d",&r[i]);
  for(int i=1;i<=m;i++)
    scanf("%d%d%d",&d[i],&s[i],&t[i]);
  if(check(m)){puts("0");return 0;} 
  printf("-1\n%d",find()+1);//匹配失败的订单
  return 0;
}

5. Luogu P1902 刺杀大使

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=1005;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int n,m,p[N][N];
bool vis[N][N];

bool dfs(int x,int y,int P){
  if(x==n) return true;
  vis[x][y]=true;
  for(int i=0; i<4; ++i){
    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 true;
  }   //P大,易true
  return false;
}
int find(){ 
  int l=-1,r=1001;
  while(l+1<r){
    int mid=l+r>>1;
    memset(vis,0,sizeof vis);
    if(dfs(1,1,mid)) r=mid; //最小化
    else l=mid;
  }
  return r;
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1; i<=n; i++) 
    for(int j=1; j<=m; j++)
      scanf("%d",&p[i][j]); 
  printf("%d",find());
  return 0;
}

6. Luogu P1163 银行贷款

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int a,b,c;

bool check(double x){
  double s=a; //s为未还的钱数
  for(int i=1;i<=c;i++)
    s=s*(1+x)-b;
  return s>=0; //x大,s大
}
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(){
  scanf("%d%d%d",&a,&b,&c);
  printf("%.1lf",find()*100);
  return 0;
}

 

7. Luogu P1873 [COCI 2011/2012 #5] EKO / 砍树

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n,M,h[1000010];

bool check(int x){
  LL s=0;
  for(int i=1;i<=n;i++)
    if(h[i]>x) s+=h[i]-x;
  return s>=M; //x小,s大
}
int find(){
  int l=0,r=1e9;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) l=mid;
    else r=mid;
  }
  return l;
}
int main(){
  scanf("%d%d",&n,&M);
  for(int i=1;i<=n;i++)scanf("%d",&h[i]);
  printf("%d",find());
  return 0;
}

8. Luogu P1577 切绳子

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10005;
int n, k, a[N];

bool check(int x){
  int cnt=0;
  for(int i=1;i<=n;i++)cnt+=a[i]/x;
  return cnt>=k; //X小,cnt大
}
int find(){ 
  int l=0, r=1e7+1;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) l=mid;
    else r=mid;
  }
  return l;
}
int main(){
  cin >> n >> k;
  double x;
  for(int i=1; i<=n; i++) 
    cin>>x,a[i]=int(x*100);//转化
  printf("%.2f",find()/100.0);
  return 0;
}

9. Luogu P1824 进击的奶牛

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,C,a[100010];

bool check(int x){
  int last=0,cnt=1;
  for(int i=1;i<n;i++)
    if(a[i]-a[last]>=x) last=i,cnt++;
  return cnt>=C; //x小,cnt大
}
int find(){
  int l=0,r=1e9+1;
  while(l+1<r){
    int mid=l+r>>1;
    if(check(mid)) l=mid;
    else r=mid;
  }
  return l;
}
int main(){ 
  scanf("%d%d",&n,&C);
  for(int i=0;i<n;i++)
    scanf("%d",&a[i]);
  sort(a,a+n);
  printf("%d",find());
  return 0;
}

10. Luogu P1182 数列分段 Section II

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

int n,m,mx,a[100010];

bool check(int mid){
  int sum=0,cnt=1;
  for(int i=1;i<=n;i++){
    if(sum+a[i]<=mid)sum+=a[i]; //贪心
    else sum=a[i],cnt++; //新开一段
  }
  return cnt<=m;
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++){
    scanf("%d",&a[i]);
    mx=max(mx,a[i]); 
  }

  int l=mx-1,r=1e9+1; //注意l不能=0
  while(l+1<r){
    int mid=(l+r)>>1;
    if(check(mid)) r=mid;
    else l=mid;
  }
  printf("%d\n",r);
  return 0;
}
/*
l=mx-1的问题:
3 3
2 4 5
T:5
F:2
*/

 

练习题

Luogu P1404 平均数

Luogu P7333 [JRKSJ R1] JFCA

Luogu P8088 『JROI-5』Autumn

Luogu P2824 [HEOI2016/TJOI2016]排序

CF1486D Max Median

Luogu P5021 [NOIP2018 提高组] 赛道修建

Luogu P1084 [NOIP2012 提高组] 疫情控制

 

POJ3104 Drying

POJ3273 Monthly Expense

POJ2456 Aggressive cows

POJ2110 Mountain Walking

 POJ1905 Expanding Rods

POJ3111 K Best

POJ2018 Best Cow Fences

 

posted @ 2023-01-31 17:20  董晓  阅读(1851)  评论(2编辑  收藏  举报