光(mirror room)
光线只有遇上边界或堵塞的格子才会改变方向,所以改变方向的位置是有限的,光线的方向又最多只有四种,所以光线在循环之前改变方向的次数是O(n+m+k)级别的。我们可以模拟光线的移动。已知光线位置和光线的方向,使用二分的方法可以在O(log k)的时间复杂度内求出即将改变方向的位置和改变后的方向。
我们暂把光线的位置和方向称为光线的状态。一种状态能转移到一种且仅有一种状态。如果从状态a能转移到状态b,那么b反向后的状态能转移到a反向后的状态。所以一种状态能从一种且仅有一种状态转移而来。这就像是一种置换,所以从初始状态出发,必定会回到初始状态,并且回到初始状态之前不会重复经过某种状态。
我们对网格进行染色,有邻边的格子颜色不同,形成一个二分图。根据题目中光线反射的方式,可以发现,每当光线沿西北、东南方向前进时,只会经过一种颜色的网格,每当光线沿东北、西南方向前进时,只会经过另一种颜色的网格。所以光线在某一个格子中心时,要么只会是西北、东南方向之一,要么只会是东北、西南方向之一。
这样,如果一次循环内一个格子被重复经过,只有可能是光线以相反的两个方向进入,并且一次循环内一个格子最多被经过两次。一个格子被经过两次,所有被光线经过的格子都会被经过两次。易知,如果光线在前进过程中出现过如下两种反射,所有格子就会被经过两次。只需在模拟的过程中记录是否出现过这两种情况即可。*/
#include<bits/stdc++.h>
#define re register
#define int long long
using namespace std;
int n,m,k,x,y,direct,ans; char s[];
set<int> s1[],s2[];
map< pair<int,int>,bool>mp;
struct node{int x,y,direct;}now;
inline int read(){
re int a=,b=; re char ch=getchar();
while(ch<''||ch>'')
b=(ch=='-')?-:,ch=getchar();
while(ch>=''&&ch<='')
a=(a<<)+(a<<)+(ch^),ch=getchar();
return a*b;
}
inline pair<node,int> cal(node x){
node k;
set<int>::iterator data;
switch(x.direct)
{
case :
{
data=s1[x.x-x.y+m+].lower_bound(x.x);data--;
k.x=x.x-abs(*data-x.x)+;
k.y=x.y-abs(*data-x.x)+;
if(mp[make_pair(k.x-,k.y)]&&mp[make_pair(k.x,k.y-)])k.direct=;
else if(mp[make_pair(k.x-,k.y)]){k.y--,k.direct=;}
else if(mp[make_pair(k.x,k.y-)]){k.x--,k.direct=;}
else k.direct=;
break; }
case :
{
data=s2[x.x+x.y].lower_bound(x.x);data--;
k.x=x.x-abs(*data-x.x)+;
k.y=x.y+abs(*data-x.x)-;
if(mp[make_pair(k.x-,k.y)]&&mp[make_pair(k.x,k.y+)])k.direct=;
else if(mp[make_pair(k.x-,k.y)]){k.y++,k.direct=;}
else if(mp[make_pair(k.x,k.y+)]){k.x--,k.direct=;}
else k.direct=;
break;
}
case :
{
data=s1[x.x-x.y+m+].lower_bound(x.x);
k.x=x.x+abs(*data-x.x)-;
k.y=x.y+abs(*data-x.x)-;
if(mp[make_pair(k.x+,k.y)]&&mp[make_pair(k.x,k.y+)])k.direct=;
else if(mp[make_pair(k.x+,k.y)]){k.y++,k.direct=;}
else if(mp[make_pair(k.x,k.y+)]){k.x++,k.direct=;}
else k.direct=;
break;
}
case :
{
data=s2[x.x+x.y].lower_bound(x.x);
k.x=x.x+abs(*data-x.x)-;
k.y=x.y-abs(*data-x.x)+;
if(mp[make_pair(k.x+,k.y)]&&mp[make_pair(k.x,k.y-)])k.direct=;
else if(mp[make_pair(k.x+,k.y)]){k.y--,k.direct=;}
else if(mp[make_pair(k.x,k.y-)]){k.x++,k.direct=;}
else k.direct=;
break;
}
}
return make_pair(k,abs(*data-x.x));
}
inline bool judge(node x){
node k=x;
do{
pair<node,int> l=cal(x);
ans+=l.second;
switch(l.first.direct)
{
case :if(x.direct==)return ;break;
case :if(x.direct==)return ;break;
case :if(x.direct==)return ;break;
case :if(x.direct==)return ;break;
}
x=l.first;
}while(k.x!=x.x||k.y!=x.y||k.direct!=x.direct);
return ;
}
signed main(){
n=read(),m=read(),k=read();
for(re int i=,u,v;i<=k;i++){
u=read(),v=read();
s1[u-v+m+].insert(u);
s2[u+v].insert(u);
mp[make_pair(u,v)]=;
}
for(re int i=;i<=m+;i++){
s1[m+-i].insert();
s2[i].insert();
s1[m+n-i+].insert(n+);
s2[i+n+].insert(n+);
mp[make_pair(,i)]=;
mp[make_pair(n+,i)]=;
}
for(re int i=;i<=n;i++){
s1[i+m+].insert(i);
s2[i].insert(i);
s1[i].insert(i);
s2[i+m+].insert(i);
mp[make_pair(i,)]=;
mp[make_pair(i,m+)]=;
}
x=read(),y=read();scanf("%s",s);
if(s[]=='N'&&s[]=='W') direct=;
if(s[]=='N'&&s[]=='E') direct=;
if(s[]=='S'&&s[]=='E') direct=;
if(s[]=='S'&&s[]=='W') direct=;
now.x=x,now.y=y,now.direct=direct;
now=cal(now).first;
if(!judge(now))
{
ans--;
switch(now.direct)
{
case :now.direct=;break;
case :now.direct=;break;
case :now.direct=;break;
case :now.direct=;break;
}
judge(now);
}
printf("%lld\n",ans);
}
光(mirror room)的更多相关文章
- 搭建高可用的rabbitmq集群 + Mirror Queue + 使用C#驱动连接
我们知道rabbitmq是一个专业的MQ产品,而且它也是一个严格遵守AMQP协议的玩意,但是要想骚,一定需要拿出高可用的东西出来,这不本篇就跟大家说 一下cluster的概念,rabbitmq是erl ...
- 搭建自己私有的PKM系统,各家PKM大比拼。。附:构建自己熟悉的基础Docker,破解联通光猫
Docker这容器真是很好玩!干啥都想上docker了,快疯了. 这不,最近wiz笔记开始收费,很是不爽,需要寻求新的PKM系统了.备选及落选理由如下: wiz笔记 -- 好用,顺手.要开始收费了,不 ...
- webform 光棒效果,删除操作弹出确定取消窗口
鼠标移入onmouseover和鼠标移出onmouseout,代码里没大写我这也就不大写了.那首先,我们得获取Class为tr_item里的所有东西,也就是项标签里的数据.然后呢,我们定义一个oldC ...
- 兼容可控硅调光的一款LED驱动电路记录
1.该款电路为兼容可控硅调光的LED驱动电路,采用OB3332为开关控制IC,拓扑方案为Buck: 2.FB1:磁珠的单位是欧姆,而不是亨利,这一点要特别注意.因为磁珠的单位是按照它在某一频率 产生的 ...
- 备忘:aliyun maven mirror
<mirror> <id>alimaven</id> <name>aliyun maven</name> &l ...
- hadoop2.7下载mirror
http://mirror.bit.edu.cn/apache/hadoop/common/
- JMeter学习-034-JMeter调试工具之一---HTTP Mirror Server
通常,编程工具IDE都提供了相应的调试模块,供开发者使用,以便更快速的定位问题所在.那么在JMeter编写测试脚本的过程中,JMeter都提供了哪些调试工具供我们使用呢? JMeter常用的调试工具有 ...
- 配置 Docker 加速器(Docker Hub Mirror)
Docker 加速器是什么,我需要使用吗? 使用 Docker 的时候,需要经常从官方获取镜像,但是由于显而易见的网络原因,拉取镜像的过程非常耗时,严重影响使用 Docker 的体验.因此 DaoCl ...
- 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror) in codeforces(codeforces730)
A.Toda 2 思路:可以有二分来得到最后的数值,然后每次排序去掉最大的两个,或者3个(奇数时). /************************************************ ...
随机推荐
- 批量插入或更新操作之ON DUPLICATE KEY UPDATE用法
实际的开发过程中,可能会遇到这样的需求,先判断某一记录是否存在,如果不存在,添加记录,如果存在,则修改数据.在INSERT语句末尾指定ON DUPLICATE KEY UPDATE可以解决这类问题. ...
- <随便写>创建文件批处理文件
创建一个text文档 写入想写的程序 将后缀改为bat 例如创建一个文件夹: 双击运行bat文件就可以创建文件夹 运行结果: 需要批量处理,就用for循环生成代码,粘贴上去就行了
- 项目无法依赖Springboot打出的jar
1.原因 因为springboot-maven-plugin打包的第一级目录为Boot-INF,无法引用 2.解决 不能使用springboot项目自带的打包插件进行打包 <build> ...
- 两队列模拟一个栈,python实现
python实现两个队列模拟一个栈: class Queue(object): def __init__(self): self.stack1=[] self.stack2=[] def enqueu ...
- Java基础——List集合整理(脑图,源码,面试题)
常在知乎牛客网关注Java的一些面试,了解过校招社招常面哪些内容.Java集合不仅使用频率高而且在初面中也常常被问到,何止是常常,关于ArrayList的扩容,HashMap的一些底层等等都被问到烂了 ...
- HZOI2019 星际旅行 欧拉路
题目大意:https://www.cnblogs.com/Juve/articles/11207540.html—————————> 题解:网上都是一句话题解:将所有的边拆成两条,问题变成去掉两 ...
- CA证书制作
目录 手动制作CA证书 1.安装 CFSSL 2.初始化cfssl 3.创建用来生成 CA 文件的 JSON 配置文件 4.创建用来生成 CA 证书签名请求(CSR)的 JSON 配置文件 5.生成C ...
- 吴恩达《机器学习》课程总结(18)_照片OCR
18.1问题描述和流程图 (1)图像文字识别是从给定的一张图片中识别文字. (2)流程包括: 1.文字侦测 2.字符切分(现在不需要切分了) 3.字符分类 18.2滑动窗口 在行人检测中,滑动窗口是首 ...
- Action详解
简介 Action 是用于处理请求操作的,它是由 StrutsPrepareAndExecuteFilter 分发过来的. 在 Struts2 框架中,Action 是框架的核心类,被称为业务逻辑控制 ...
- Mysql中ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8怎么转换为sql sever2008的代码
ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8转换sql server AUTO_INCREMENT=2 ,是 自动递增列的 初始数值 = 2, ...