光(mirror room)

/*

光线只有遇上边界或堵塞的格子才会改变方向,所以改变方向的位置是有限的,光线的方向又最多只有四种,所以光线在循环之前改变方向的次数是On+m+k)级别的。我们可以模拟光线的移动。已知光线位置和光线的方向,使用二分的方法可以在Olog k)的时间复杂度内求出即将改变方向的位置和改变后的方向。

 
 

我们暂把光线的位置和方向称为光线的状态。一种状态能转移到一种且仅有一种状态。如果从状态a能转移到状态b,那么b反向后的状态能转移到a反向后的状态。所以一种状态能从一种且仅有一种状态转移而来。这就像是一种置换,所以从初始状态出发,必定会回到初始状态,并且回到初始状态之前不会重复经过某种状态。

 
 

我们对网格进行染色,有邻边的格子颜色不同,形成一个二分图。根据题目中光线反射的方式,可以发现,每当光线沿西北、东南方向前进时,只会经过一种颜色的网格,每当光线沿东北、西南方向前进时,只会经过另一种颜色的网格。所以光线在某一个格子中心时,要么只会是西北、东南方向之一,要么只会是东北、西南方向之一。

 
 

这样,如果一次循环内一个格子被重复经过,只有可能是光线以相反的两个方向进入,并且一次循环内一个格子最多被经过两次。一个格子被经过两次,所有被光线经过的格子都会被经过两次。易知,如果光线在前进过程中出现过如下两种反射,所有格子就会被经过两次。只需在模拟的过程中记录是否出现过这两种情况即可。*/

  1 #include<bits/stdc++.h>
  2 #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<node,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<node,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 }

猜你喜欢

转载自www.cnblogs.com/Hzoi-lyl/p/11232996.html
今日推荐