A06 二分答案
#include<bits/stdc++.h> using namespace std; const int N=100005; int n,k,a[N]; bool check(int x){ long long cnt=0; //段数 for(int i=1;i<=n;i++) cnt+=a[i]/x; return cnt>=k; } int main(){ scanf("%d%d",&n,&k); for(int i=1; i<=n; i++)scanf("%d",&a[i]); int l=0, r=1e8+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; //最大化 else r=mid; } printf("%d\n",l); return 0; }
2. Luogu P2678 [NOIP2015 提高组] 跳石头
#include<bits/stdc++.h> using namespace std; int L,n,m,a[500005]; bool check(int x){ int last=0,cnt=0; for(int i=1;i<=n;i++) if(a[i]-a[last]<x) cnt++;//贪心 else last=i; return cnt<=m; } int main(){ scanf("%d%d%d",&L,&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); a[++n]=L; //右边界 int l=0,r=1e9+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; //最大化 else r=mid; } printf("%d\n",l); return 0; }
3. Luogu P1314 [NOIP2011 提高组] 聪明的质监员
#include<bits/stdc++.h> using namespace std; const int N=200010; int n,m,w[N],v[N],l[N],r[N]; long long s,sn[N],sv[N],ans=1e18; bool check(int x){ memset(sn,0,sizeof sn); memset(sv,0,sizeof sv); for(int i=1;i<=n;i++){ //前缀和 if(w[i]>=x)sn[i]=sn[i-1]+1,sv[i]=sv[i-1]+v[i]; else sn[i]=sn[i-1],sv[i]=sv[i-1]; } long long 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; } 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]); int l=0,r=1e6+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) r=mid; //最小化 else l=mid; } printf("%lld",ans); return 0; }
4. Luogu P1083 [NOIP2012 提高组] 借教室
#include<bits/stdc++.h> using namespace std; const int N=1000010; int n,m,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; } 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;} int l=0,r=m+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; //最大化 else r=mid; } printf("-1\n%d",l+1); //匹配失败的订单 return 0; }
#include<bits/stdc++.h> 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; } return false; } 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]); 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; } printf("%d",r); return 0; }
#include<bits/stdc++.h> 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; } int main(){ scanf("%d%d%d",&a,&b,&c); double l=0, r=10; while(r-l>1e-5){ double mid=(l+r)/2; if(check(mid)) r=mid; //最小化 else l=mid; } printf("%.1lf",r*100); return 0; }
7. Luogu P1873 [COCI 2011/2012 #5] EKO / 砍树
#include<bits/stdc++.h> using namespace std; int n,M,h[1000010]; bool check(int x){ long long s=0; for(int i=1;i<=n;i++) if(h[i]>x) s+=h[i]-x; return s>=M; } int main(){ scanf("%d%d",&n,&M); for(int i=1;i<=n;i++)scanf("%d",&h[i]); int l=0,r=1e9; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; else r=mid; } printf("%d",l); return 0; }
#include<bits/stdc++.h> 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; } int main(){ cin >> n >> k; double x; for(int i=1; i<=n; i++) cin>>x,a[i]=int(x*100);//转化 int l=0,r=1e7+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; else r=mid; } printf("%.2f",l/100.0); return 0; }
#include<bits/stdc++.h> 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; } int main(){ scanf("%d%d",&n,&C); for(int i=0;i<n;i++)scanf("%d",&a[i]); sort(a,a+n); int l=0,r=1e9+1; while(l+1<r){ int mid=l+r>>1; if(check(mid)) l=mid; else r=mid; } printf("%d",l); return 0; }
10. Luogu P1182 数列分段 Section II
#include<bits/stdc++.h> 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 P2824 [HEOI2016/TJOI2016]排序
Luogu P5021 [NOIP2018 提高组] 赛道修建
Luogu P1084 [NOIP2012 提高组] 疫情控制
浙公网安备 33010602011771号