光(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个(奇数时). /************************************************ ...
随机推荐
- idea配置tomcat中war和war exploded的区别
是选择war还是war exploded 这里首先看一下他们两个的区别: war模式:将WEB工程以包的形式上传到服务器 :war exploded模式:将WEB工程以当前文件夹的位置关系上传到服务器 ...
- day 39 MySQL之多表查询
MySQL之多表查询 阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都 ...
- 2016 CCPC网络选拔赛 部分题解
HDU 5832 - A water problem 题意:有两颗星球,一年的长度分别为37天和173天.问第n天时它们是否为新年的第一天. 思路:显然 n 同时被37和173整除时,两种历法都在新 ...
- java基础之final关键字
final: 意为终态.在java中得注意以下四点: 1.final是一个修饰符,可修饰变量,方法,类. 2.final修饰子类不可以被继承. 3.final修饰的方法不可以被重写(覆盖) 4.对于一 ...
- linux下mysql导入导出sql文件
使用mysqldump导出数据库: # mysqldump -u root -p gzy > gzy.sql # mysqldump -u 数据库连接用户名 -p 目标数据库 > 存储的文 ...
- 如何将Map键值的下划线转为驼峰
本文不再更新,可能存在内容过时的情况,实时更新请移步我的新博客:如何将Map键值的下划线转为驼峰: 例,将HashMap实例extMap键值下划线转为驼峰: 代码: HashMap<String ...
- Python pylint的安装和使用
Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准和有潜在问题的代码. Pylint 是一个 Python 工具,除了平常代码分析工具的作用之 ...
- anime.js 学习笔记
官网演示/文档 anime.js 是一个简便的JS动画库,用法简单而且适用范围广,涵盖CSS,DOM,SVG还有JS的对象,各种带数值属性的东西都可以动起来. 实际演示和代码,官网写得很详细清楚了,这 ...
- c语言学习笔记 函数数组传递笔记
今天学习c语言的一个小例子,果然还是陷入了php的编程习惯里,这里记录一下. #include <stdio.h> //例子很简单,就是编写一个函数把传递进来的数组里的值都赋值为1而已 / ...
- 科普 | 编译 V8 源码
2017-02-13 justjavac 象尘说 对于JavaScript程序员来说,可以瞧一瞧justjavac给大家写的科普类读物,V8引擎的分析,“也许你不懂C++”,但是你可以了解一下,总是好 ...