【HNOI 2018】游戏
【HNOI 2018】游戏
Problem
Description
一次小 \(G\) 和小 \(H\) 在玩寻宝游戏,有 \(n\) 个房间排成一列,编号为 \(1,2,…,n\),相邻房间之间都有 \(1\) 道门。其中一部分门上有锁(因此需要对应的钥匙才能开门),其余的门都能直接打开。
现在小 \(G\) 告诉了小 \(H\) 每把锁的钥匙在哪个房间里(每把锁有且只有一把钥匙),并作出 \(p\) 次指示:第 \(i\) 次让小 H 从第 \(S_i\) 个房间出发,去第 \(T_i\) 个房间寻宝。但是小 \(G\) 有时会故意在指令里放入死路,而小 \(H\) 也不想浪费多余的体力去尝试,于是想事先调查清楚每次的指令是否存在一条通路。
你是否能为小 \(H\) 作出解答呢?
Input Format
第一行三个整数\(n\),\(m\),\(p\),代表共有 \(n\) 个房间,\(m\) 道门上了锁,以及 \(p\) 个询问。
接下来 \(m\) 行每行有两个整数\(x\),\(y\),代表第 \(x\) 到第 \(x + 1\) 个房间的门上有把锁,并且这把锁的钥匙被放在了第 \(y\) 个房间里。输入保证 \(x\) 不重复。
接下来 \(p\) 行,其中第 \(i\) 行是两个整数 \(S_i\),\(T_i\),代表一次询问。
Output Format
输出 \(m\) 行,每行一个大写的 YES
或 NO
分别代表能或不能到达。
Sample
Input 1
5 4 5
1 3
2 2
3 1
4 4
2 5
3 5
4 5
2 1
3 1
Output 1
YES
NO
YES
YES
NO
Input 2
此组样例满足特性:\(y \le x\) 恒成立
7 5 4
2 2
3 3
4 2
5 3
6 6
2 1
3 4
3 7
4 5
Output 2
YES
YES
NO
NO
Explanation
Explanation for Input 1
第一个询问 \(S = 2\)、\(T = 5\) 的一条可行路线是:\(2 \rightarrow 3 \rightarrow 2 \rightarrow 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5\)。
Explanation for Input 2
第一个询问 \(2\) 和 \(1\) 房间之间没有锁所以为一条通路。
Range
测试点编号 | n | m | 其他特性 |
---|---|---|---|
1 | \(\le 1000\) | \(\le 1000\) | 无 |
2 | \(\le 1000\) | \(\le 1000\) | 无 |
3 | \(\le 10^5\) | \(\le 10^5\) | \(y \le x\) 恒成立 |
4 | \(\le 10^5\) | \(\le 10^5\) | \(y \le x\) 恒成立 |
5 | \(\le 10^5\) | \(\le 10^5\) | 无 |
6 | \(\le 10^5\) | \(\le 10^5\) | 无 |
7 | \(\le 10^6\) | \(\le 10^6\) | \(y \le x\) 恒成立 |
8 | \(\le 10^6\) | \(\le 10^6\) | \(y \le x\) 恒成立 |
9 | \(\le 10^6\) | \(\le 10^6\) | 无 |
10 | \(\le 10^6\) | \(\le 10^6\) | 无 |
Algorithm
线段树,单调栈。
Mentality
基本思路:设 \(r[i]\) 与 \(l[i]\) 为从 \(i\) 出发的能到达的区间,求出后对于每个询问 \(O(1)\) 判断就好。
这一题我们先从 \(60\) 分的做法看起:
- 暴力拓展左右端点,复杂度 \(O(n^2)\),\(20pts\) 。
- 对于所有 \(y\le x\) 的点用单调栈,\(40pts\) 。
暴力并不难,我们看看 \(40pts\) 的单调栈怎么做。其实不能算得上是什么神仙思路,类似于并查集,各扇门将序列分成了一些小区间,如果你通过此区间能到达其他区间,那么其他区间能到达的所有区间你也能到达。这就是此题单调栈的思路。
首先,既然所有 \(y\le x\) ,可以知道,我们向左走,一旦碰到一扇门就肯定走不过去了,那么我们只需要考虑最多能向右走多远就行了。
这个向右走的过程我们使用单调栈来维护:如果我们此时能到达的区间里有通向右边相邻区间的钥匙,那一旦到达当前区间,我必定能到达下一个区间,那么将两个区间合并为一个区间即可。
此处应有小代码:
bool pd(int x)
{return key[r[x]]>=l[x]&&key[r[x]]<=r[x];
}
for(int i=n;i>=1;i--)
{stack[++top]=r[i];//r[i]为初始区间右端点while(pd(i))//如果当前区间右端点的钥匙在区间内r[i]=stack[--top];//更新右端点并栈内合并区间
}
\(40pts\) 解决了,那 \(100\) 分呢?
其实也很简单,我们唯一的难点仅在于左端点也会更新。所以我们只需要能在当前右端点条件下快速求出左端点能扩展到多远即可。
根据 \(y\le x\) 的情况,我们可以类推得到:向左走时,一旦钥匙在门左边,那就肯定过不去;向右走时,一旦钥匙在门右边,那肯定也过不去。
于是我们可以求出 \(ll[i]\) 与 \(rr[i]\) 来代表 \(i\) 所能到达区间的理论上界 (最大的左右端点只可能是 \(ll\) 与 \(rr\))。
那不难发现,我当前能走到的区间是 \([l,r]\) ,而对于 \(l\) 的扩展,一定能扩展到 \([ll,l-1]\) 里最右边的,钥匙位置 \(>r\) 的位置后边。
为什么呢?因为根据我们的筛法,区间 \([ll,l-1]\) 内的门的钥匙肯定都在门右边 (不然 \(ll\) 只会更右) ,则此区间内门的钥匙要么 \(\le r\) 要么 \(>r\) ,同时又在自己右边,那钥匙位置 \(\le r\) 的门肯定都可以打开的呀!
那么和之前是一模一样的,只是判断单调栈弹出之前先更新左端点即可:
bool pd(int x)
{update_l(x);return key[r[x]]>=l[x]&&key[r[x]]<=r[x];
}
for(int i=n;i>=1;i--)
{stack[++top]=r[i];while(pd(i))r[i]=stack[--top];
}
至于具体怎么更新左端点呢?我们只需要找到区间 \([ll,l-1]\) 中,第一个 \(\ge r[i]\) 的位置就好。我们可以用线段树维护区间钥匙位置最大值,并在线段树上查找就好,设查找到的位置为 \(pos\) ,左端点更新为 \(pos+1\) 即可。
Code
#include<iostream>
#include<cstdio>
using namespace std;
#define ls (o<<1)
#define rs ((o<<1)+1)
#define mid ((l+r)>>1)
int n,m,Q,key[1000001],ll[1000001],rr[1000001],l[1000001],r[1000001];
int now,top,stack[1000001];
int L,R,X,ans,maxx[4000001];
void build(int o,int l,int r)
{if(l==r){maxx[o]=key[l];return;}build(ls,l,mid),build(rs,mid+1,r);maxx[o]=max(maxx[ls],maxx[rs]);
}
void query(int o,int l,int r)
{if(ans)return;if(l==r){ans=l;return;}if(mid<R&&maxx[rs]>X)query(rs,mid+1,r);//显然先找右区间哇if(mid>=L&&maxx[ls]>X)query(ls,l,mid);
}
bool pd(int x)
{L=ll[x],R=l[x]-1,X=r[x],ans=0;query(1,1,n);l[x]=!ans?ll[x]:ans+1;//更新左端点return key[r[x]]>=l[x]&&key[r[x]]<=r[x];
}
int main()
{freopen("4436.in","r",stdin);freopen("4436.out","w",stdout);cin>>n>>m>>Q;int x,t,now,tp;for(int i=1;i<=m;i++)scanf("%d",&x),scanf("%d",&key[x]);now=1,tp=1;for(int i=1;i<=n;i++){if(key[i-1]){now=i;if(key[i-1]<i)tp=i;}ll[i]=tp,l[i]=now;}now=n,tp=n;for(int i=n;i>=1;i--){if(key[i]){now=i;if(key[i]>i)tp=i;}rr[i]=tp,r[i]=now;}//处理出 l,r,ll,rrbuild(1,1,n);//建树stack[++top]=n;for(int i=n;i>=1;i--){stack[++top]=r[i];while(pd(i))r[i]=stack[--top];}//求出 l,rwhile(Q--){scanf("%d%d",&x,&t);printf(t>=l[x]&&t<=r[x]?"YES\n":"NO\n");}
}
【HNOI 2018】游戏相关推荐
- HNOI 2018 游记
前言 为什么我又现在才写一个星期前的游记QAQ,马上都要自己省的省选了还来这里吹水... 还有,这是今年第几次来长沙了?.. 为什么一点紧张感都没有啊,吃枣药丸啊 Day0 上午坐高铁出发,几乎全程补 ...
- 2018校招笔试真题汇总(javaC++)
科大讯飞: 2018秋招笔试科大讯飞java笔试试题 https://www.nowcoder.com/discuss/67684?type=2&order=3&pos=13& ...
- 2018校招笔试真题汇总(java/C++)
科大讯飞: 2018秋招笔试科大讯飞java笔试试题 https://www.nowcoder.com/discuss/67684?type=2&order=3&pos=13& ...
- 体验游戏,就在即刻!Google Play Instant
一直以来,我们都在努力使 Google Play 成为玩家发现更多游戏和开发者获得更大成功的舞台.在过去的一年里,安装游戏的 Android 用户量增长了一倍多,其中将近 40% 的增长来自于巴西.印 ...
- MobData研究院,一个操作让游戏 营销ROI 翻了3倍
MobData研究院,一个操作让游戏 营销ROI 翻了3倍 近些年中国移动游戏迎来了大爆发,2017年收入超过1161亿元,同比增长41.7%.但在人口红利的消失下,各大渠道从增量转变成了存量,增长速 ...
- python pip升级为什么升级不了_python pip升级失败
Python微信-- 分享接口(分享到朋友圈.朋友.空间) 生成JS-SDK权限验证的签名 获取signature(签名)首先要获得 1.#获得jsapi_ticket 2.#获取当前页面的url # ...
- 其他-私人♂收藏(比赛记录 Mar, 2019)
OwO 03.03 [USACO19JAN] A. Redistricting 题意:给 \(g\) ,求 \(f(n)\) . \(f(i)=f(j)+[g(i)\ge g(j)],j \in (i ...
- 捕获标志位_如何通过捕获标志挑战来提高网络安全技能-PicoCTF演练
捕获标志位 Want to improve your cybersecurity / ethical hacking skills but don't know where to start? Cyb ...
- wegame饥荒一直登录中_经历网游和单机发行的左右摇摆后,Wegame决定“我全都要”...
在5月12日结束的<剑网3>大师赛现场上,制作人郭炜炜宣布了与腾讯WeGame的联运合作计划,在网游.单机谁为重心的左右摇摆后,Wegame也终于明确了自己在整个腾讯游戏布局中的定位:所有 ...
最新文章
- SAP事务码f-02做账界面显示“页数”字段
- POJ 2389 Bull Math(大数乘大数)
- 1.2 UML带来了什么(学习笔记)
- 电气:电能扰动质量数据集模拟生成(matlab)
- http使用post上传文件时,请求头和主体信息总结
- java占32位存储空间时,java空间
- 黄聪:PHP去掉转义后字符串中的反斜杠\函数stripslashes
- 软件工程复习提纲——第二章
- 设置log缓存_全局变量、事件绑定、缓存爆炸?Node.js内存泄漏问题分析
- 递归--练习11--noi9273 PKU2506Tiling
- PHP水仙花问题解法之一
- python自学篇——PyGame模块的所有功能函数详解
- 【面试题】网易互娱(游戏)2021校园招聘在线笔试 - 服务端开发工程师[螺旋矩阵]
- 测试用例设计——微信发朋友圈(详细)
- 项目需求|眼镜试戴app(ios)
- GIF一下你也可以拍大片 微影戏程序
- 靶机渗透练习13-hackme1
- 点云数据按高程赋色渲染
- STM32F767串口通信学习笔记
- 辐射强度 BRDF概念定义明晰
热门文章
- scrapy淘宝爬虫(通过模拟登录获取cookie)获取价格信息评论
- 服装店管理软件有哪些功能?
- 基于 Verilog 的经典数字电路设计(2)比较器
- Python3---可迭代对象(iterable)、迭代器(iterator)、生成器(generator)的理解和应用
- ModuleNotFoundError: No module named ‘yaml‘解决方案
- java uno游戏_为什么我怎么也明白uno牌C++和JAVA算法实现
- 金蝶k3怎么显示服务器地址,金蝶k3如何查询连接的服务器配置
- Kotlin自定义一个简单实用的标题栏
- VS2013链接MYSQL数据库
- 开机自检磁盘时间过长,如何屏蔽磁盘检测?