Codeforces 724C [坐标][乱搞][模拟]

/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
从(0,0)出发与x轴正方向呈45度角的射线,在给定的矩形区域内不断发射,直到射入矩形的某个角停止。
给出多个坐标,问光线最早经过某坐标的时间。
思路:
1.明确光线反射次数不会超过n+m次(好像是这样==没细想)
2.发现规律,光线要么是符合x+y=k,或者x-y=k的直线。而且每次反射都会变到不同类型的直线。
3.知道出发点,算出反射点。
4.把点放到直线的vector里边。每次到了某条直线把直线上的点扫一遍,然后删掉。

*/


#include<bits/stdc++.h>
using namespace std;
struct point{
    point(){}
    point(long long xx,long long yy,int iid){
        x=xx;y=yy;id=iid;
    }
    long long x,y,id;
};
bool operator <(const point &a,const point &b){
    if(a.x!=b.x)return a.y<b.y;
    return a.x<b.x;
}
set<point> ms1[200050],ms2[200050];
long long rel[100050];
int n,m,k;
point next(point a,int num){
    if(num&1){
        long long w=a.x+a.y;
        long long x=0;
        long long y=w-x;
        if(y>=0&&y<=m&&(x!=a.x||y!=a.y))return point(x,y,0);
        x=n;
        y=w-x;
        if(y>=0&&y<=m&&(x!=a.x||y!=a.y))return point(x,y,0);
        y=0;
        x=w-y;
        if(x>=0&&x<=n&&(x!=a.x||y!=a.y))return point(x,y,0);
        y=m;
        x=w-y;
        if(x>=0&&x<=n&&(x!=a.x||y!=a.y))return point(x,y,0);
    }
    else{
        long long w=a.x-a.y;
        long long x=0;
        long long y=x-w;
        if(y>=0&&y<=m&&(x!=a.x||y!=a.y))return point(x,y,0);
        x=n;
        y=x-w;
        if(y>=0&&y<=m&&(x!=a.x||y!=a.y))return point(x,y,0);
        y=0;
        x=y+w;
        if(x>=0&&x<=n&&(x!=a.x||y!=a.y))return point(x,y,0);
        y=m;
        x=y+w;
        if(x>=0&&x<=n&&(x!=a.x||y!=a.y))return point(x,y,0);
    }
}
long long cal(point a,point b){
    return max(a.x-b.x,b.x-a.x);
}
int main()
{
    memset(rel,-1,sizeof(rel));
    long long x,y,bf=0;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;i++){
        scanf("%lld%lld",&x,&y);
        ms1[x-y+100000].insert(point(x,y,i));
        ms2[x+y].insert(point(x,y,i));
    }
    point st(0,0,0);
    int num=0;
    while(1){
        x=st.x;y=st.y;
        if(num&1){
            while(!ms2[x+y].empty()){
                long long xx=ms2[x+y].begin()->x;
                long long yy=ms2[x+y].begin()->y;
                int id=ms2[x+y].begin()->id;
                if(rel[id]==-1)
                rel[id]=bf+cal(point(xx,yy,0),st);
                ms1[x-y+100000].erase(point(xx,yy,0));
                ms2[x+y].erase(point(xx,yy,0));
            }
        }
        else{
            while(!ms1[x-y+100000].empty()){
                long long xx=ms1[x-y+100000].begin()->x;
                long long yy=ms1[x-y+100000].begin()->y;
                int id=ms1[x-y+100000].begin()->id;
                if(rel[id]==-1)
                rel[id]=bf+cal(point(xx,yy,0),st);
                ms1[x-y+100000].erase(point(xx,yy,0));
                ms2[x+y].erase(point(xx,yy,0));
            }
        }
        bf+=cal(st,next(st,num));
        st=next(st,num);
        num++;
        if((st.x==0&&st.y==0)||(st.x==0&&st.y==m)||(st.x==n&&st.y==0)||(st.x==n&&st.y==m))break;
    }
    for(int i=1;i<=k;i++){
        printf("%lld
",rel[i]);
    }
}
原文地址:https://www.cnblogs.com/tun117/p/5943929.html