【JZOJ4823】小W学物理

来源:互联网 发布:数据库导论 pdf 编辑:程序博客网 时间:2024/06/12 00:56

Description

为了测试小W的物理水平,Mr.X在二维坐标系中放了N面镜子(镜子坐标绝对值不超过M),镜子均与坐标轴成45°角,所以一共有两种类型“/”和“\”。原点不会有镜子,任意一点最多只有一面镜子。
镜子两个面都能反光,而中间不透光,例如,对于一个“/”型镜子,下方向射入的光线会被反射到右方向,左方向射入的光线会被反射到上方向。
现在有一条光线从原点沿X轴正方向射出,求走过T路程后所在位置。

Solution

结论1:如果光线不形成环,那么每面镜子至多经过两次。

结论2:如果光线形成环,那么光线通过反射后一定重新经过原点。

那么直接模拟光线走到哪即可。

注意特判一些情况。

数据水,不判环可以过。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 100001#define ll long longusing namespace std;struct node{    ll x,y;    int z,c;}a[N],zx[N],zy[N];int cx[N],cy[N];ll bz[N][2][2];bool cmpx(node x,node y){    if(x.x==y.x) return x.y<y.y;    else return x.x<y.x;}bool cmpy(node x,node y){    if(x.y==y.y) return x.x<y.x;    else return x.y<y.y;}ll abss(ll x){    return x<0?-x:x;}node pp;int main(){    freopen("mir.in","r",stdin);    freopen("mir.out","w",stdout);    int n;    ll m,t;    cin>>n>>m>>t;    fo(i,1,n)    {        char ch;        scanf("%lld %lld %c",&pp.x,&pp.y,&ch);        if(ch=='/') pp.z=1;        else pp.z=-1;        a[i]=zx[i]=zy[i]=pp;    }    sort(a+1,a+n+1,cmpx);    fo(i,1,n) a[i].c=i;    sort(a+1,a+n+1,cmpy);    fo(i,1,n) cx[a[i].c]=i,a[i].c=i;    sort(a+1,a+n+1,cmpx);    fo(i,1,n) cy[a[i].c]=i;    sort(zx+1,zx+n+1,cmpx);    sort(zy+1,zy+n+1,cmpy);    int p=0,q=0;    fo(i,1,n)    if(zy[i].y==0 && zy[i].x>0)    {        p=cy[i];        break;    }    ll s=zx[p].x,ss;    if(s>=t || !p)    {        printf("%lld 0",t);        return 0;    }    int z=zx[p].z,fx=1;    bz[p][fx][1]=s;    while(s<t)    {        ss=s;        if(fx==1)        {            q=p;            p+=z;            if(zx[p].x!=zx[q].x)            {                printf("%lld %lld",zx[q].x,zx[q].y+z*(t-s));                break;            }            s+=abss(zx[p].y-zx[q].y);            if(s>=t)            {                printf("%lld %lld",zx[q].x,zx[q].y+z*(t-ss));                break;            }            fx=0;        }        else        {            q=p;            p=cy[cx[p]+z];            if(zx[p].y!=zx[q].y)            {                printf("%lld %lld",zx[q].x+z*(t-s),zx[q].y);                return 0;            }            s+=abss(zx[p].x-zx[q].x);            if(s>=t)            {                printf("%lld %lld",zx[q].x+z*(t-ss),zx[q].y);                break;            }            fx=1;        }        int zz=z;        if(zz==-1) zz++;        if(bz[p][fx][zz])        {            ll s1=s-bz[p][fx][zz];            ll s2=t-s;            s+=(s2/s1)*s1;        }        bz[p][fx][zz]=s;        z*=zx[p].z;    }}
1 0