Time Limit: 1 Sec
Memory Limit: 162 MB
具体做法就是先按斜率由小到大排序,然后依次处理,将当前直线与栈顶直线求交点,然后判断交点在栈顶减1的直线的左侧还是右侧(假定每一条直线是方向自左向右的向量,通过求叉积判左右),在右侧就踢掉栈顶的直线,一直做到可行。最后入栈。
Description
Input
第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi
Output
从小到大输出可见直线的编号,两两中间用空格隔开.
Sample Input
3
-1 0
1 0
0 0
-1 0
1 0
0 0
Sample Output
1 2
题解:这题很像半平面交,不过只求半个,所以只要简单的用一个栈维护就可以了。
错误:直线判平行一开始只做了一次。。其实一直要做到踢完所有平行的。(反正就是很水的错。。还Output Limit Exceed。。。)
AC CODE
program
hy_1007;
const
eps=1e-
7
;
type
line=
record
x1,y1,x2,y2:
extended
;
end
;
dotype=
record
x,y:
extended
;
end
;
var
l:
array
[
1..50000
]
of
line;
k,b:
array
[
1..50000
]
of
extended
;
a,stack:
array
[
1..50000
]
of
longint
;
n,i,top:
longint
;
dott:dotype;
//============================================================================
procedure
qsort(s,t:
longint
);
var
i,j,tt:
longint
;
kk:
extended
;
begin
kk:=k[a[(s+t)
div
2
]]; i:=s; j:=t;
repeat
while
k[a[i]]<kk
do
inc(i);
while
k[a[j]]>kk
do
dec(j);
if
i<=j
then
begin
tt:=a[i]; a[i]:=a[j]; a[j]:=tt;
inc(i); dec(j);
end
;
until
i>j;
if
j>s
then
qsort(s,j);
if
i<t
then
qsort(i,t);
end
;
//============================================================================
procedure
qsort2(s,t:
longint
);
var
kk,i,j,tt:
longint
;
begin
kk:=stack[(s+t)
div
2
]; i:=s; j:=t;
repeat
while
stack[i]<kk
do
inc(i);
while
stack[j]>kk
do
dec(j);
if
i<=j
then
begin
tt:=stack[i]; stack[i]:=stack[j]; stack[j]:=tt;
inc(i); dec(j);
end
;
until
i>j;
if
j>s
then
qsort2(s,j);
if
i<t
then
qsort2(i,t);
end
;
//============================================================================
function
dot(a,b:line):dotype;
var
s1,s2,k:
extended
;
begin
s1:=(b
.
x1-a
.
x1)*(a
.
y2-a
.
y1)-(a
.
x2-a
.
x1)*(b
.
y1-a
.
y1);
s2:=(a
.
x2-a
.
x1)*(b
.
y2-a
.
y1)-(b
.
x2-a
.
x1)*(a
.
y2-a
.
y1);
k:=s1/(s1+s2);
dot
.
x:=b
.
x1+(b
.
x2-b
.
x1)*k;
dot
.
y:=b
.
y1+(b
.
y2-b
.
y1)*k;
end
;
//============================================================================
function
right(a:dotype; b:line):
boolean
;
begin
if
(b
.
x2-b
.
x1)*(a
.
y-b
.
y1)-(a
.
x-b
.
x1)*(b
.
y2-b
.
y1)<=eps
then
exit(
true
)
else
exit(
false
);
end
;
//============================================================================
begin
readln(n);
for
i:=
1
to
n
do
begin
a[i]:=i; readln(k[i],b[i]);
l[i].x1:=-
1000
; l[i].x2:=
1000
;
l[i].y1:=l[i].x1*k[i]+b[i];
l[i].y2:=l[i].x2*k[i]+b[i];
end
; qsort(
1
,n);
stack[
1
]:=a[
1
]; top:=
1
;
for
i:=
2
to
n
do
begin
while
top>
0
do //错在这里了。。原来只是判断了一次,就跳掉了。
if
(k[stack[top]]=k[a[i]])
and
(b[a[i]]>b[stack[top]])
then
dec(top)
else
break;
if
k[a[i]]=k[stack[top]]
then
continue;
while
top>
1
do
begin
dott:=dot(l[stack[top]],l[a[i]]);
if
right(dott,l[stack[top-
1
]])
then
dec(top)
else
break;
end
;
inc(top); stack[top]:=a[i];
end
;
qsort2(
1
,top);
for
i:=
1
to
top
do
write
(stack[i],
' '
);
end
.