题目描述
我今天又没有学习。MDZ
没有学习的MDZ热爱玩各种弹球游戏,所以这是一道弹球题。
有一个 $n$ 行 $m$ 列的网格,其中 $n$ 与 $m$ 互质且 $m$ 为奇数。 左下角坐标 $(0,0)$ ,右上角坐标 $(m,n)$ 。
初始一个大小忽略的小球处在 $(m/2,0)$ 处,初始速度向量为 $(-1/2,1/2)$ (即初始向左上方走)。
某些格子有方块,当遇到网格的边界或者方块的边界时,就会发出镜面反射。如果球撞到某个方块,这个方块就会消失。
现在已经每个方块的位置,问多长时间后所有方块消失。
数据范围
$1 leq n, m, k leq 10^{5}, quad k leq mn-1$
题解
考虑暴力,将每个方块拆成四条边,用set维护x+y和x-y相等的边。
考虑如果碰到边界该怎么办,发现如果这次从一个边界通过一个方向到达了一个边界,那下次这个边界通过这个方向的时候还是会到达这个边界,于是用并查集压缩一下路径即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=4e5+5; int m,n,k,t,f[N<<3]; struct P{int x,y;}p[N]; long long ans,g[N<<3]; struct O{ int x,y,i; friend bool operator < (const O& A,const O& B){ if (A.x==B.x){ if (A.y==B.y) return A.i<B.i; return A.y<B.y; } return A.x<B.x; } }; set<O>s[2][N]; set<O>::iterator it; #define pi pair<int,int> #define M make_pair #define fi first #define se second map<pair<pi,pi>,int>mp; pair<pi,pi>h[N<<3]; void ins(int x,int y,int i){ s[0][x+y].insert((O){x,y,i}); s[1][x-y+n].insert((O){x,y,i}); } void era(int x,int y,int i){ s[0][x+y].erase(s[0][x+y].find((O){x,y,i})); s[1][x-y+n].erase(s[1][x-y+n].find((O){x,y,i})); } void era(int i){ int x=p[i].x,y=p[i].y; era(x-2,y-1,i);era(x-1,y,i); era(x-1,y-2,i);era(x,y-1,i);k--; } int get(int x){ return f[x]==x?x:f[x]=get(f[x]); } int main(){ cin>>m>>n>>k;m<<=1;n<<=1; for (int i=1,x,y;i<=k;i++){ scanf("%d%d",&x,&y); x<<=1;y<<=1;p[i]=(P){x,y}; ins(x-2,y-1,i);ins(x-1,y,i); ins(x-1,y-2,i);ins(x,y-1,i); } int x=m>>1,y=0,dx=-1,dy=1,o,v; if (!mp.count(M(M(x,y),M(dx,dy)))) mp[M(M(x,y),M(dx,dy))]=++t, f[t]=t,h[t]=M(M(x,y),M(dx,dy)); while(k){ o=0; if (mp.count(M(M(x,y),M(dx,dy)))) o=mp[M(M(x,y),M(dx,dy))]; if (dx<0 && dy>0){ it=s[0][x+y].lower_bound((O){x,0,0}); if (it==s[0][x+y].begin()){ if (x+y>n) g[get(o)]+=n-y,ans+=n-y,x=x+y-n,y=n,dy=-1; else g[get(o)]+=x,ans+=x,y=x+y,x=0,dx=1; if (!mp.count(M(M(x,y),M(dx,dy)))) mp[M(M(x,y),M(dx,dy))]=++t, f[t]=t,h[t]=M(M(x,y),M(dx,dy)); v=mp[M(M(x,y),M(dx,dy))]; ans+=g[get(v)]; x=h[get(v)].fi.fi,y=h[get(v)].fi.se, dx=h[get(v)].se.fi,dy=h[get(v)].se.se; if (!o) continue; g[get(v)]+=g[get(o)]; f[get(o)]=get(v); continue; } it--;O u=*it;era(u.i);ans+=x-u.x;x=u.x;y=u.y; if (y&1) dx=1; else dy=-1; continue; } if (dx>0 && dy<0){ it=s[0][x+y].upper_bound((O){x,0,0}); if (it==s[0][x+y].end()){ if (x+y-m>0) g[get(o)]+=m-x,ans+=m-x,y=x+y-m,x=m,dx=-1; else g[get(o)]+=y,ans+=y,x=x+y,y=0,dy=1; if (!mp.count(M(M(x,y),M(dx,dy)))) mp[M(M(x,y),M(dx,dy))]=++t, f[t]=t,h[t]=M(M(x,y),M(dx,dy)); v=mp[M(M(x,y),M(dx,dy))]; ans+=g[get(v)]; x=h[get(v)].fi.fi,y=h[get(v)].fi.se, dx=h[get(v)].se.fi,dy=h[get(v)].se.se; if (!o) continue; g[get(v)]+=g[get(o)]; f[get(o)]=get(v); continue; } O u=*it;era(u.i);ans+=u.x-x;x=u.x;y=u.y; if (y&1) dx=-1; else dy=1; continue; } if (dx>0 && dy>0){ it=s[1][x-y+n].upper_bound((O){x,0,0}); if (it==s[1][x-y+n].end()){ if (m-x+y<n) g[get(o)]+=m-x,ans+=m-x,y=m-x+y,x=m,dx=-1; else g[get(o)]+=n-y,ans+=n-y,x=x-y+n,y=n,dy=-1; if (!mp.count(M(M(x,y),M(dx,dy)))) mp[M(M(x,y),M(dx,dy))]=++t, f[t]=t,h[t]=M(M(x,y),M(dx,dy)); v=mp[M(M(x,y),M(dx,dy))]; ans+=g[get(v)]; x=h[get(v)].fi.fi,y=h[get(v)].fi.se, dx=h[get(v)].se.fi,dy=h[get(v)].se.se; if (!o) continue; g[get(v)]+=g[get(o)]; f[get(o)]=get(v); continue; } O u=*it;era(u.i);ans+=u.x-x;x=u.x;y=u.y; if (y&1) dx=-1; else dy=-1; continue; } if (dx<0 && dy<0){ it=s[1][x-y+n].lower_bound((O){x,0,0}); if (it==s[1][x-y+n].begin()){ if (y-x>0) g[get(o)]+=x,ans+=x,y=y-x,x=0,dx=1; else g[get(o)]+=y,ans+=y,x=x-y,y=0,dy=1; if (!mp.count(M(M(x,y),M(dx,dy)))) mp[M(M(x,y),M(dx,dy))]=++t, f[t]=t,h[t]=M(M(x,y),M(dx,dy)); v=mp[M(M(x,y),M(dx,dy))]; ans+=g[get(v)]; x=h[get(v)].fi.fi,y=h[get(v)].fi.se, dx=h[get(v)].se.fi,dy=h[get(v)].se.se; if (!o) continue; g[get(v)]+=g[get(o)]; f[get(o)]=get(v); continue; } it--;O u=*it;era(u.i);ans+=x-u.x;x=u.x;y=u.y; if (y&1) dx=1; else dy=1; continue; } } cout<<ans<<endl; return 0; }