/*
光线只有遇上边界或堵塞的格子才会改变方向,所以改变方向的位置是有限的,光线的方向又最多只有四种,所以光线在循环之前改变方向的次数是O(n+m+k)级别的。我们可以模拟光线的移动。已知光线位置和光线的方向,使用二分的方法可以在O(log k)的时间复杂度内求出即将改变方向的位置和改变后的方向。
我们暂把光线的位置和方向称为光线的状态。一种状态能转移到一种且仅有一种状态。如果从状态a能转移到状态b,那么b反向后的状态能转移到a反向后的状态。所以一种状态能从一种且仅有一种状态转移而来。这就像是一种置换,所以从初始状态出发,必定会回到初始状态,并且回到初始状态之前不会重复经过某种状态。
我们对网格进行染色,有邻边的格子颜色不同,形成一个二分图。根据题目中光线反射的方式,可以发现,每当光线沿西北、东南方向前进时,只会经过一种颜色的网格,每当光线沿东北、西南方向前进时,只会经过另一种颜色的网格。所以光线在某一个格子中心时,要么只会是西北、东南方向之一,要么只会是东北、西南方向之一。
这样,如果一次循环内一个格子被重复经过,只有可能是光线以相反的两个方向进入,并且一次循环内一个格子最多被经过两次。一个格子被经过两次,所有被光线经过的格子都会被经过两次。易知,如果光线在前进过程中出现过如下两种反射,所有格子就会被经过两次。只需在模拟的过程中记录是否出现过这两种情况即可。*/
1 #include2 #define re register 3 #define int long long 4 using namespace std; 5 int n,m,k,x,y,direct,ans; char s[4]; 6 set<int> s1[200001],s2[200001]; 7 map< pair<int,int>,bool>mp; 8 struct node{int x,y,direct;}now; 9 inline int read(){ 10 re int a=0,b=1; re char ch=getchar(); 11 while(ch<'0'||ch>'9') 12 b=(ch=='-')?-1:1,ch=getchar(); 13 while(ch>='0'&&ch<='9') 14 a=(a<<3)+(a<<1)+(ch^48),ch=getchar(); 15 return a*b; 16 } 17 inline pair int> cal(node x){ 18 node k; 19 set<int>::iterator data; 20 switch(x.direct) 21 { 22 case 1: 23 { 24 data=s1[x.x-x.y+m+1].lower_bound(x.x);data--; 25 k.x=x.x-abs(*data-x.x)+1; 26 k.y=x.y-abs(*data-x.x)+1; 27 if(mp[make_pair(k.x-1,k.y)]&&mp[make_pair(k.x,k.y-1)])k.direct=3; 28 else if(mp[make_pair(k.x-1,k.y)]){k.y--,k.direct=4;} 29 else if(mp[make_pair(k.x,k.y-1)]){k.x--,k.direct=2;} 30 else k.direct=3; 31 break; 32 33 } 34 case 2: 35 { 36 data=s2[x.x+x.y].lower_bound(x.x);data--; 37 k.x=x.x-abs(*data-x.x)+1; 38 k.y=x.y+abs(*data-x.x)-1; 39 if(mp[make_pair(k.x-1,k.y)]&&mp[make_pair(k.x,k.y+1)])k.direct=4; 40 else if(mp[make_pair(k.x-1,k.y)]){k.y++,k.direct=3;} 41 else if(mp[make_pair(k.x,k.y+1)]){k.x--,k.direct=1;} 42 else k.direct=4; 43 break; 44 } 45 case 3: 46 { 47 data=s1[x.x-x.y+m+1].lower_bound(x.x); 48 k.x=x.x+abs(*data-x.x)-1; 49 k.y=x.y+abs(*data-x.x)-1; 50 if(mp[make_pair(k.x+1,k.y)]&&mp[make_pair(k.x,k.y+1)])k.direct=1; 51 else if(mp[make_pair(k.x+1,k.y)]){k.y++,k.direct=2;} 52 else if(mp[make_pair(k.x,k.y+1)]){k.x++,k.direct=4;} 53 else k.direct=1; 54 break; 55 } 56 case 4: 57 { 58 data=s2[x.x+x.y].lower_bound(x.x); 59 k.x=x.x+abs(*data-x.x)-1; 60 k.y=x.y-abs(*data-x.x)+1; 61 if(mp[make_pair(k.x+1,k.y)]&&mp[make_pair(k.x,k.y-1)])k.direct=2; 62 else if(mp[make_pair(k.x+1,k.y)]){k.y--,k.direct=1;} 63 else if(mp[make_pair(k.x,k.y-1)]){k.x++,k.direct=3;} 64 else k.direct=2; 65 break; 66 } 67 } 68 return make_pair(k,abs(*data-x.x)); 69 } 70 inline bool judge(node x){ 71 node k=x; 72 do{ 73 pair int> l=cal(x); 74 ans+=l.second; 75 switch(l.first.direct) 76 { 77 case 1:if(x.direct==3)return 0;break; 78 case 2:if(x.direct==4)return 0;break; 79 case 3:if(x.direct==1)return 0;break; 80 case 4:if(x.direct==2)return 0;break; 81 } 82 x=l.first; 83 }while(k.x!=x.x||k.y!=x.y||k.direct!=x.direct); 84 return 1; 85 } 86 signed main(){ 87 n=read(),m=read(),k=read(); 88 for(re int i=1,u,v;i<=k;i++){ 89 u=read(),v=read(); 90 s1[u-v+m+1].insert(u); 91 s2[u+v].insert(u); 92 mp[make_pair(u,v)]=1; 93 } 94 for(re int i=0;i<=m+1;i++){ 95 s1[m+1-i].insert(0); 96 s2[i].insert(0); 97 s1[m+n-i+2].insert(n+1); 98 s2[i+n+1].insert(n+1); 99 mp[make_pair(0,i)]=1; 100 mp[make_pair(n+1,i)]=1; 101 } 102 for(re int i=1;i<=n;i++){ 103 s1[i+m+1].insert(i); 104 s2[i].insert(i); 105 s1[i].insert(i); 106 s2[i+m+1].insert(i); 107 mp[make_pair(i,0)]=1; 108 mp[make_pair(i,m+1)]=1; 109 } 110 x=read(),y=read();scanf("%s",s); 111 if(s[0]=='N'&&s[1]=='W') direct=1; 112 if(s[0]=='N'&&s[1]=='E') direct=2; 113 if(s[0]=='S'&&s[1]=='E') direct=3; 114 if(s[0]=='S'&&s[1]=='W') direct=4; 115 now.x=x,now.y=y,now.direct=direct; 116 now=cal(now).first; 117 if(!judge(now)) 118 { 119 ans--; 120 switch(now.direct) 121 { 122 case 1:now.direct=3;break; 123 case 2:now.direct=4;break; 124 case 3:now.direct=1;break; 125 case 4:now.direct=2;break; 126 } 127 judge(now); 128 } 129 printf("%lld\n",ans); 130 }