二分边界

根据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;
}

 

posted @ 2018-03-31 22:59  谨川  阅读(235)  评论(0编辑  收藏  举报