小W学物理
题目大意
在二维坐标系中放了
N
面镜子(镜子坐标绝对值不超过
镜子两个面都能反光,中间不透光,例如,对于一个’/’型镜子,下方向射入的光线会被反射到右方向。
现在有一条光线从原点沿
X
轴正方向射出,求光线走过
数据范围
对于
100
%的数据,
N
<=
题解
这一题,看上去很难,实际上很简单。
首先,假设光线不会经过原点,那么每一面镜子撑死经过两次(镜子两面各一次),且不会存在环的情况,那么最多走2N次镜子后,就不会再经过镜子了。对于每一面镜子,可以通过排序预处理出它上下左右的第一面镜子即可。
倘若光线经过的原点且再次经过原点时是沿X轴的正方向射出的,则说明出现了环,这时只需令T变为(T mod 环的的长度)再重新从原点跑一遍即可。
Code(Pascal)
label 123,234;
var
ch:char;
n,m,t,ans,x,y:int64;
i,j,k,l,o,p,fx,uu:longint;
mi,fz:Array[0..100100,1..3] of int64;
procedure sjzl;
var
i,k:longint;
begin
for i:=1 to n div 2 do
begin
k:=n div 2+random(n div 2)+1;
mi[0]:=mi[i];
mi[i]:=mi[k];
mi[k]:=mi[0];
end;
end;
procedure qsort(l,r:longint);
var
i,j,m,mm:longint;
begin
i:=l;
j:=r;
m:=mi[(l+r) div 2,1];
mm:=mi[(l+r) div 2,2];
repeat
while (mi[i,1]<m) or ((mi[i,1]=m) and (mi[i,2]<mm)) do inc(i);
while (mi[j,1]>m) or ((mi[j,1]=m) and (mi[j,2]>mm)) do dec(j);
if i<=j then
begin
mi[0]:=mi[i];
mi[i]:=mi[j];
mi[j]:=mi[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure qsortt(l,r:longint);
var
i,j,m,mm:longint;
begin
i:=l;
j:=r;
m:=fz[(l+r) div 2,2];
mm:=fz[(l+r) div 2,1];
repeat
while (fz[i,2]<m) or ((fz[i,2]=m) and (fz[i,1]<mm)) do inc(i);
while (fz[j,2]>m) or ((fz[j,2]=m) and (fz[j,1]>mm)) do dec(j);
if i<=j then
begin
fz[0]:=fz[i];
fz[i]:=fz[j];
fz[j]:=fz[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsortt(l,j);
if i<r then qsortt(i,r);
end;
function efh(kx,ky:longint):longint;
var
l,r,mid:longint;
begin
l:=1;
r:=n+2;
while l+1<r do
begin
mid:=(l+r) div 2;
if (mi[mid,1]<kx) or (mi[mid,1]=kx) and (mi[mid,2]<=ky) then l:=mid
else r:=mid;
end;
efh:=l;
end;
function efl(kx,ky:longint):longint;
var
l,r,mid:longint;
begin
l:=1;
r:=n+2;
while l+1<r do
begin
mid:=(l+r) div 2;
if (fz[mid,2]<ky) or (fz[mid,2]=ky) and (fz[mid,1]<=kx) then l:=mid
else r:=mid;
end;
efl:=l;
end;
begin
readln(n,m,t);
for i:=1 to n do
begin
read(mi[i,2],mi[i,1]);
read(ch);
readln(ch);
if ch='/' then mi[i,3]:=1
else mi[i,3]:=2;
end;
sjzl;
mi[n+1,1]:=0;
mi[n+1,2]:=0;
fz:=mi;
qsort(1,n+1);
qsortt(1,n+1);
x:=0;
y:=0;
mi[n+2,1]:=t+1;
mi[n+2,2]:=mi[n+2,1];
fz[n+2]:=mi[n+2];
fz[0]:=fz[n+2];
mi[0]:=fz[0];
fx:=4;
123:
while true do
begin
if fx mod 2=0 then uu:=efh(x,y)
else uu:=efl(x,y);
if (fx=1) or (fx=4) then inc(uu) else dec(uu);
if fx mod 2=0 then
begin
if mi[uu,1]<>x then goto 234;
ans:=ans+abs(mi[uu,1]-x)+abs(mi[uu,2]-y);
x:=mi[uu,1];
y:=mi[uu,2];
if ans>=t then
begin
if fx=4 then y:=y-(ans-t)
else y:=y+(ans-t);
writeln(y,' ',x);
halt;
end;
if (fx=4) and (mi[uu,3]=1) then fx:=1
else if (fx=4) and (mi[uu,3]=2) then fx:=3
else if (fx=2) and (mi[uu,3]=1) then fx:=3
else fx:=1;
if (mi[uu,1]=0) and (mi[uu,2]=0) then
begin
t:=t mod ans;
x:=0;
y:=0;
fx:=4;
ans:=0;
goto 123;
end;
end
else
begin
if fz[uu,2]<>y then goto 234;
ans:=ans+abs(fz[uu,1]-x)+abs(fz[uu,2]-y);
x:=fz[uu,1];
y:=fz[uu,2];
if ans>=t then
begin
if fx=1 then x:=x-(ans-t)
else x:=x+(ans-t);
writeln(y,' ',x);
halt;
end;
if (fz[uu,1]=0) and (fz[uu,2]=0) then fx:=fx
else
if (fx=1) and (fz[uu,3]=1) then fx:=4
else if (fx=1) and (fz[uu,3]=2) then fx:=2
else if (fx=3) and (fz[uu,3]=1) then fx:=2
else fx:=4;
end;
end;
234:
if fx=1 then x:=x+(t-ans);
if fx=3 then x:=x-(t-ans);
if fx=2 then y:=y-(t-ans);
if fx=4 then y:=y+(t-ans);
writeln(y,' ',x);
end.