Listing WTELL.PAS 
Program Tell; 
{$B-,F+,I-,N+,R-,S-} 
Const NMax=3000; 
Type PointType=record X,Y:Extended end; 
PointVector=array[-1..NMax]of PointType; 
BoolFunc=Function(i,j:Integer):Boolean; 
Var P:PointVector; 
N,M,NSecants,IndMinX,IndMaxX:Integer; 
{ Indicii punctelor extreme pe X } 
A,B,C,SumDist:Extended; 
Better:BoolFunc; { Criteriul folosit } 
{ la maximizare (Greater/Less) } 
Procedure ReadPoints; 
{ Citeste punctele si calculeaza } 
{ indicii minimului & maximului pe X } 
Var i:Integer; 
begin 
Readln(N); IndMinX:=0; IndMaxX:=0; 
for i:=0 to N-1 do 
with P[i] do 
begin 
Readln(X,Y); 
if X<P[IndMinX].X then IndMinX:=i; 
if X>P[IndMaxX].X then IndMaxX:=i 
end; 
NSecants:=0; SumDist:=0 
end; 
Function Dist(i:Integer):Extended; 
{ Distanta de la un punct } 
{ la o dreapta (normalizata) } 
begin 
Dist:=A*P[i].X+B*P[i].Y+C 
end; 
Function Greater(i,j:Integer):Boolean; 
{ Arata daca P[i] este "mai mare" } 
{ ca P[j] relativ la directia dreptei } 
begin 
Greater:=(Dist(i)>=Dist(j)) 
end; 
Function Less(i,j:Integer):Boolean; 
{ Arata daca P[i] este "mai mic" } 
{ ca P[j] relativ la directia dreptei } 
begin 
Less:=(Dist(i)<=Dist(j)) 
end; 
Function FindBest(Lo,Hi:Integer; 
Better:BoolFunc):Integer; 
{ Intoarce indicele punctului optim pe } 
{ directia vectorului de componente A si B.} 
{ "Optim" inseamna fie "maxim", fie "minim"} 
{ dupa cum Better este Greater sau Less } 
{ (criteriul de comparatie) } 
Var Mid:Integer; 
Finished:Boolean; 
begin 
Finished:=False; 
while((Hi+N-Lo) mod N>1) and not Finished do 
begin 
if Hi>Lo 
then Mid:=(Lo+Hi) div 2 
else Mid:=((Lo+Hi+N) div 2) mod N; 
{ Sare peste 0 } 
if Better(Mid,(Mid+1) mod N) 
then Hi:=Mid 
else 
if Better(Mid,(Mid+N-1) mod N) 
then Lo:=Mid 
else Finished:=True 
{ Suntem intr-o groapa } 
end; 
if Better(Hi,Lo) then FindBest:=Hi 
else FindBest:=Lo 
end; 
Procedure CountDistance(Min,Max:Integer); 
{ Vede daca minimul si maximul gasite dupa } 
{ directia ceruta sunt: } 
{ a) De parti diferite ale dreptei -> } 
{ dreapta e secanta, distanta e zero } 
{ b) De aceeasi parte, distanta este a } 
{ celui mai apropiat dintre ele } 
Var DMin, DMax:Extended; 
begin 
DMin:=Dist(Min); 
DMax:=Dist(Max); 
if DMin*DMax<=0 
then Inc(NSecants) 
else 
if Abs(DMin)<Abs(DMax) 
then SumDist:=SumDist+Abs(DMin) 
else SumDist:=SumDist+Abs(Dmax) 
end; 
Procedure CheckLines; 
Var i:Integer; 
Max,Min,Candidate:Integer; 
D:Extended; 
begin 
Readln(M); 
for i:=1 to M do 
begin 
Readln(A,B,C); 
{ Normalizam ecuatia dreptei } 
D:=Sqrt(A*A+B*B); 
A:=A/D; 
B:=B/D; 
C:=C/D; 
{ Cautam punctul MAXIM dupa directia } 
{ data, pe ambele lanturi } 
Max:=FindBest(IndMinX,IndMaxX,Greater); 
Candidate:=FindBest(IndMaxX,IndMinX,Greater); 
if Greater(Candidate,Max) 
then Max:=Candidate; 
{ Cautam punctul MAXIM dupa directia } 
{ data, pe ambele lanturi } 
Min:=FindBest(IndMinX,IndMaxX,Less); 
Candidate:=FindBest(IndMaxX,IndMinX,Less); 
if Less(Candidate,Min) 
then Min:=Candidate; 
CountDistance(Min,Max) 
end 
end; 
Begin 
Assign(Input,'TELL.IN'); 
Reset(Input); 
Assign(Output,'TELL.OUT'); 
Rewrite(Output); 
ReadPoints; 
CheckLines; 
Writeln(NSecants); 
Writeln(SumDist:0:2); 
Close(Input); 
Close(Output) 
End.