二分边界
根据l r的实际意义确定边界条件
根据达到边界前的临界(最后一次二分) 判断答案和l r mid的关系
l r根据实际意义或为了答案能取到0、n 可能变为0 n+1
看清题目问的是满足条件的还是不满足条件的,最小值还是最大值
满足条件的最大值
while l<=r do 左不确定右不确定 l-1肯定满足
mid:=(l+r) div 2;
if ok then l:=mid+1 ans:=mid
else r:=mid-1
ans=r;
l是第一个不满足的位置
inc(r)
while l<r-1 do 左满足右不满足
mid:=(l+r) div 2
if ok then begin l:=mid;ans:=mid;end;
else r:=mid
ans=l
inc(r)左不确定右不满足
while l<r do
mid:=(l+r) div 2
if ok then l:=mid+1//ans:=mid
else r:=mid
ans=l-1 or r-1 //ans
while l<r do 左满足右不确定
mid:=(l+r+1) div 2 为了临界r=l+1时,因为l已经满足,要验证r 若mid=(l+r)/2 验证的是l
if ok then l:=mid
else r:=mid-1
l r
满足条件的最小值
while(l<=r){
int mid=l+r>>1;
for(i=f=1;i<=n && f<=m;i++,f++) while(f<=m && abs(a[i]-b[f])+abs(b[f])>mid) f++;
if(i==n+1 && f<=m+1) ans=mid,r=mid-1;
else l=mid+1;
ans l
while l<r do 左不确定右满足
mid:=(l+r) div 2
if ok then r:=mid
else l:=mid+1
l r
第一个不满足条件的位置
l:=1;r:=m+1; repeat mid:=(l+r) div 2;s:=0;f:=0; for i:=l to mid do begin inc(sum[b[i].s],b[i].d);dec(sum[b[i].t+1],b[i].d); end; for i:=1 to n do begin inc(s,sum[i]); if s>rr[i] then begin f:=-1;break;end; end; if f=-1 then begin r:=mid;ans:=mid; for i:=l to mid do begin dec(sum[b[i].s],b[i].d);inc(sum[b[i].t+1],b[i].d); end; end else l:=mid+1; until l=r; if l=m+1 then writeln(0) else begin writeln(-1); writeln(l); end;
l:=1;r:=m+1; while l<=r do begin mid:=(l+r) div 2;s:=0;f:=0; for i:=l to mid do begin inc(sum[b[i].s],b[i].d);dec(sum[b[i].t+1],b[i].d); end; for i:=1 to n do begin inc(s,sum[i]); if s>rr[i] then begin f:=-1;break;end; end; if f=-1 then begin r:=mid-1;ans1:=mid; for i:=l to mid do begin dec(sum[b[i].s],b[i].d);inc(sum[b[i].t+1],b[i].d); end; end else begin l:=mid+1;ans2:=mid;end; end; if l=m+2 then writeln(0)//ans2=m+1 else begin writeln(-1); writeln(l);//ans2+1 ans1 end;
很奇怪17年的时候洛谷35 19就又a了
l:=1;r:=m;//l=0 repeat mid:=(l+r) div 2;s:=0;f:=0; for i:=l to mid do begin inc(sum[b[i].s],b[i].d);dec(sum[b[i].t+1],b[i].d); end; for i:=1 to n do begin inc(s,sum[i]); if s>rr[i] then begin;f:=-1;break;end; end; if f=-1 then begin r:=mid-1; for i:=l to mid do begin dec(sum[b[i].s],b[i].d);inc(sum[b[i].t+1],b[i].d); end; end else begin l:=mid+1;ans:=mid;end; until l>r; if l=m+1 then writeln(0) else begin writeln(-1); writeln(ans+1); end; end.
lower_bound源码
//count表示在当前二分区域还有多少个数没进行判断 左(first)闭右(last)开 last已经判断过或者数组结束位置(空地址、元素) 肯定满足条件 //count==1时,判断first 若不符合first变为last count==0 循环结束 //符合 first不变 count==0 循环结束 //第四个参数是比较函数 默认< greater<int>()是自带的比较函数 相当于> 加greater<int>() 改变了if的判断条件 变为 if(*it>val) template <class ForwardIterator, class T> ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val) { ForwardIterator it; iterator_traits<ForwardIterator>::difference_type count, step; count = distance(first, last); while(count > 0) { it = first; step = count / 2; advance(it, step); if (*it < val) { // or: if (comp(*it,val)), for version (2) first = ++it; count -= step + 1; } else count = step; } return first; }