二分

模板:while l<=r do

       begin

         mid:=(l+r)div 2;

        if check() then begin ans:=mid;l:=mid+1;(1)end 最大值时 最小值时1 2对调

       else r:=mid-1;(2)

 

1. 跳石头 (https://www.luogu.org/problemnew/show/2678#sub)   

var
a:array [0..100005] of longint;
v,n,p,i,l,r,m,u,s,ans:longint;
begin
read(v,n,p);
for i:=1 to n do read(a[i]);
a[0]:=0; a[n+1]:=v; inc(n);
l:=0; r:=v;
while (l<=r) do begin
m:=(l+r) div 2;
s:=a[0]; u:=0;
for i:=1 to n do
if (a[i]-s>=m) then s:=a[i] else inc(u);
if (u>p) then r:=m-1 else begin l:=m+1;ans:=m;end;
end;
write(ans);
end.

2 借教室

  

type
node=record
d,s,t:longint;
end;
var
f:integer;
mid,n,m,l,r,i,ans:longint;
b:array [1..1000000] of node;
rr:array [1..1000000] of longint;
sum:array [1..1000001] of int64;
s:int64;
begin
readln(n,m);
for i:=1 to n do read(rr[i]);
readln;
for i:=1 to m do
with b[i] do//可以学的地方
readln(d,s,t);

fillchar(sum,sizeof(sum),0);
l:=0;r:=m;
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 ans=m+1 then writeln(0)//都搜过去了l=m
else begin
writeln(-1);
writeln(ans+1);
end;
end.

3 聪明的质检员

var
n,m,ss,ans,min:int64;
j:longint;
g,s,w,v,q,p:array[-1..200010] of int64;
l,r,fk:int64;

begin
readln(n,m,ss);
for j:=1 to n do
readln(w[j],v[j]);
for j:=1 to m do
readln(p[j],q[j]);
l:=0; r:=1000000000; min:=-1;
while r>=l do
begin
fk:=(l+r)div 2; g[0]:=0; s[0]:=0; ans:=0;
for j:=1 to n do
if w[j]>=fk then begin g[j]:=g[j-1]+1; s[j]:=s[j-1]+v[j]; end
else begin g[j]:=g[j-1]; s[j]:=s[j-1]; end;
for j:=1 to m do
ans:=ans+(g[q[j]]-g[p[j]-1])*(s[q[j]]-s[p[j]-1]);
if ((min=-1)or(abs(ans-ss)<min)) then min:=abs(ans-ss);
if ans>ss then l:=fk+1 else r:=fk-1;
end;
writeln(min);
end.

posted @ 2017-11-26 20:07  谨川  阅读(174)  评论(0)    收藏  举报