二分例题
链接:https://ac.nowcoder.com/acm/problem/14504
来源:牛客网
题目描述
有 n 棵树,初始时每棵树的高度为 Hi,第 i 棵树每月都会长高 Ai。现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于L,而且木料必须是整棵树(即不能为树的一部分)。现在问你最少需要等多少个月才能满足订单。
输入描述:
第一行 3 个用空格隔开的非负整数 n,S,L,表示树的数量、订单总量和单块木料长度限制。
第二行 n 个用空格隔开的非负整数,依次为 H1,H2,... ,Hn。
第三行 n 个用空格隔开的非负整数,依次为 A1,A2,... ,An。
输出描述:
输出一行一个整数表示答案。
示例1
输入
复制
3 74 51
2 5 2
2 7 9
输出
复制
7
说明
对于样例,在六个月后,各棵树的高度分别为 14,47,56,此时无法完成订单。
在七个月后,各棵树的高度分别为 16,54,65,此时可以砍下第 2 和第 3 棵树完成订单了。
备注:
1≤n≤200000,1≤S,L≤1018,1≤Hi,Ai≤109
二分具体看代码吧,也有注释,我太菜了,看了大佬代码才会的。。。。。。。
//https://ac.nowcoder.com/acm/problem/14504 //二分,利用范围是0到最大月份,但为了避免出现界限不够问题,最好多开一位,比如这道题, //当增长数组大于 max(要的木材和最小量) ,不多开的话,很可能输出0,实际是1年 #include using namespace std; #define ll long long const int N=2e5+20; ll q[N],a[N]; ll n,lll,s; bool check(ll mid)//二分的判断函数,利用月份 { ll sum=0,x; for(int i=0;i<n;i++) { x=q[i]+a[i]*mid; if(x<lll) continue;//判断这个月份的树合适不 sum+=x; if(sum>=s) return true; } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); ll t,r=0,l=0; cin>>n>>s>>lll; for(int i=0;i>q[i]; for(int i=0;i<n;i++) { cin>>a[i]; r=max(r,a[i]); } r=max(s,lll)/r+1;////当增长数组大于 max(要的木材和最小量) ,不多开的话,很可能输出0,实际是1年 while(l<r)//套板子开始了 { ll mid=l+r>>1;//注意用ll,我当初用的int,然后暴了,最后显示超时 if(check(mid)) r=mid; else l=mid+1; } cout<<l<<endl; return 0; }