题目:
“我是超级大沙茶”——Mato_No1
为了证明自己是一个超级大沙茶,Mato 神犇决定展示自己对叉(十字型)有多么的了解。
Mato 神犇有一个平面直角坐标系,上面有一些线段,保证这些线段至少与一条坐标轴平行。Mato 神犇需要指出,这些线段构成的最大的十字型有多大。
称一个图形为大小为R(R 为正整数)的十字型,当且仅当,这个图形具有一个中心点,它存在于某一条线段上,并且由该点向上下左右延伸出的长度为R 的线段都被已有的线段覆盖。
你可以假定:没有两条共线的线段具有公共点,没有重合的线段。
input:
输入1: 1 0 0 0 1 输入2: 3 -1 0 5 0 0 -1 0 1 2 -2 2 2
output:
输出1: Human intelligence is really terrible 输出2: 2
分析:
此题暴力水解。正解平衡树+二分。水解就是按长度排序一遍这些线段。然后如果n>5000,那么我们就取前5000个来做O(n^2)的枚举。因为是排序的,如果在前五千找到了最优解,只要数据不是很强,就能水过去。。
代码:
const
maxn=100000;
var
x1,y1,x2,y2,b,c,w:array [0..maxn] of longint;
a:array [0..maxn] of 0..1;
flag:boolean;
n:longint;
procedure init;
var
i,j:longint;
begin
readln(n);
for i:=1 to n do
begin
readln(x1[i],y1[i],x2[i],y2[i]);
if x1[i]=x2[i] then
begin
a[i]:=1;
if y1[i]>y2[i] then
begin
j:=y1[i];
y1[i]:=y2[i];
y2[i]:=j;
end;
end
else
if x1[i]>x2[i] then
begin
j:=x1[i];
x1[i]:=x2[i];
x2[i]:=j;
end;
end;
end;
function min(a,b:longint):longint;
begin
if a<b then
exit(a);
exit(b);
end;
procedure main;
var
i,j,ans:longint;
begin
ans:=0;
for i:=1 to n do
for j:=i+1 to n do
if a[i]<>a[j] then
if a[i]=1 then
begin
if (x1[i]>x1[j]) and (x1[i]<x2[j]) and (y1[j]<y2[i]) and (y1[j]>y1[i]) then
begin
if min(min(x1[i]-x1[j],x2[j]-x1[i]),min(y1[j]-y1[i],y2[i]-y1[j]))>ans then
ans:=min(min(x1[i]-x1[j],x2[j]-x1[i]),min(y1[j]-y1[i],y2[i]-y1[j]));
flag:=true;
end;
end
else
begin
if (x1[j]>x1[i]) and (x1[j]<x2[i]) and (y1[i]<y2[j]) and (y1[i]>y1[j]) then
begin
if min(min(x1[j]-x1[i],x2[i]-x1[j]),min(y1[i]-y1[j],y2[j]-y1[i]))>ans then
ans:=min(min(x1[j]-x1[i],x2[i]-x1[j]),min(y1[i]-y1[j],y2[j]-y1[i]));
flag:=true;
end;
end;
if flag then
write(ans)
else
write('Human intelligence is really terrible');
end;
begin
assign(input,'line.in');reset(input);
assign(output,'line.out');rewrite(output);
init;
main;
close(input);close(output);
end.