Description
为了测试小W的物理水平,Mr.X在二维坐标系中放了N面镜子(镜子坐标绝对值不超过M),镜子均与坐标轴成45°角,所以一共有两种类型“/”和“\”。原点不会有镜子,任意一点最多只有一面镜子。
镜子两个面都能反光,而中间不透光,例如,对于一个“/”型镜子,下方向射入的光线会被反射到右方向,左方向射入的光线会被反射到上方向。
现在有一条光线从原点沿X轴正方向射出,求走过T路程后所在位置。
Input
第一行三个整数N,M,T。
第2到N+1行,每行两个整数Xi,Yi,表示镜子坐标,一个字符Si表示镜子类型
Output
一行两个整数,表示走过T路程后的坐标。
Sample Input
5 2 8
0 1 \
0 2 /
1 0 /
1 1 \
1 2 \
Sample Output
3 1
Data Constraint
对于10%的数据:N=1
对于25%的数据:T<=1000000
对于35%的数据:N<=1000
对于60%的数据:M<=1000
对于100%的数据:N<=100,000,M<=1,000,000,000,T<=10^18
Solution
乍一看好熟悉
曾经有一题几乎一样的,模拟,但是这题的范围!!
显然时间复杂度不能和T有关
一种显然的思路,找出每个点上下左右的最近的点,每次跳过去就行了,这样每个点最多经过4次,时间复杂度为
O(4n)
但是有一点,因为它的出发点在图内,所以是可能有循环的
那就对于每个点的每个方向做一个标记,记录到达的时间,那么第二次到达时,就可以跳过循环节,直接进入最后一次循环
Code
有些人表示打了100多行,我很奇怪,怎么打的?我的代码量折半
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 200100
#define ll long long
using namespace std;
struct node{
ll x,y,z,d;
};
node a[N];
ll l[N][4],b[N][4],s,ax,ay,c[N][3],bz[N][4],ddd[4]={-1,1,0,0},dddd[4]={0,0,1,-1},ct[3][4]={{0,0,0,0},{3,2,1,0},{2,3,0,1}};
bool cnt(node x,node y){return (x.x<y.x)||((x.x==y.x)&&(x.y<y.y));}
bool cnt2(node x,node y){return (x.y<y.y)||((x.y==y.y)&&(x.x<y.x));}
int main()
{
freopen("mir.in","r",stdin);freopen("mir.out","w",stdout);
ll t,n,m,f=1;
scanf("%lld%lld%lld",&n,&m,&t);
fo(i,1,n)
{
char ch;
scanf("%lld %lld %ch\n",&a[i].x,&a[i].y,&ch);
if(ch=='/') c[i][2]=1;else c[i][2]=2;
a[i].d=i;c[i][0]=a[i].x;c[i][1]=a[i].y;
}
sort(a+1,a+n+1,cnt);
fo(i,1,n)
{
if(a[i-1].x==a[i].x) l[a[i].d][3]=a[i].y-a[i-1].y,b[a[i].d][3]=a[i-1].d;
if(a[i+1].x==a[i].x) l[a[i].d][2]=a[i+1].y-a[i].y,b[a[i].d][2]=a[i+1].d;
}
sort(a+1,a+n+1,cnt2);
fo(i,1,n)
{
if(a[i-1].y==a[i].y) l[a[i].d][0]=a[i].x-a[i-1].x,b[a[i].d][0]=a[i-1].d;
if(a[i+1].y==a[i].y) l[a[i].d][1]=a[i+1].x-a[i].x,b[a[i].d][1]=a[i+1].d;
if(a[i].y==0&&a[i].x>0&&s==0)
if(a[i].y<t) s=a[i].d,t-=a[i].x;else ax=t,ay=0,t=0;
}
if(s==0) ax=t,ay=0,t=0;
for(;t;)
{
if(bz[s][f]!=0) t=t%(bz[s][f]-t);
bz[s][f]=t;f=ct[c[s][2]][f];
if(l[s][f]<t&&b[s][f]!=0) t-=l[s][f],s=b[s][f];
else ax=c[s][0]+ddd[f]*t,ay=c[s][1]+dddd[f]*t,t=0;
}
printf("%lld %lld",ax,ay);
fclose(stdin);fclose(stdout);
}