问题描述

一次小G和小H在玩寻宝游戏,有n个房间排成一列,编号为1,2,...,n,相邻的房间之间都有一道门。其中一部分门上锁(因此需要有对应的钥匙才能开门),其余的门都能直接打开。现在小G告诉了小H每把锁的钥匙在哪个房间里(每把锁有且只有一把钥匙与之对应),并作出p次指示:第i次让小H从第\(S_i\)个房间出发到\(T_i\)个房间里。但是小G有时会故意在指令中放入死路,而小H也不想浪费多余的体力去尝试,于是想事先调查清楚每次的指令是否会存在一条通路。

你是否能为小H作出解答呢?

输入格式

第一行三个数字:n,m,p,代表有n个房间,m道门上了锁,以及p个询问。接下来m行,每行两个数字x,y代表x到x+1的钥匙在房间y。接下来p行,其中第i行是两个整数\(S_i,T_i\),代表一次询问。

输出格式

输出p行,每行一个“YES”或"NO",分别代表能或不能到达。

样例输入

5 4 5

1 3

2 2

3 1

4 4

2 5

3 5

4 5

2 1

3 1

样例输出

YES

NO

YES

YES

NO

说明

解析

可以发现对于每个点i,最后能到达的区域一定是一段区间[Li,Ri]。那么问题就是如何求这些区间。

如果一扇门的钥匙在这扇门的左边,那么就不能从右边穿过这扇门;如果在这扇门的右边,就不能从左边穿过去。那么,如果我们对每扇门的两边,由不能到达的向能到达的连边,可以发现一个点的区间范围一定可以由拓扑序在这个点前面的点得到(只有前面的点有边连向这个点)。所以,可以利用拓扑排序,对队首的点,向左向右扩展,扩展的点注意门的编号等于门右边的编号减一,具体见代码。

但是,对于一个可以互达的区间,有可能会连成一个环,这样拓扑排序就没有意义了。所以,最开始需要预处理能够互达的区间,并将这个区间缩成一个点。同时将所有信息更新成缩点之后的。

回答询问时,只需判断T是否在S的可达区间中即可。

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <queue>
  5. #define N 1000002
  6. #define M 1000002
  7. using namespace std;
  8. int head[N],ver[M],nxt[M],d[N],t;
  9. int n,m,q,i,x[N],y[N],pos[N],cnt=1,gap[N],l[N],r[N];
  10. bool lock[N];
  11. int read()
  12. {
  13. char c=getchar();
  14. int w=0;
  15. while(c<'0'||c>'9') c=getchar();
  16. while(c<='9'&&c>='0'){
  17. w=w*10+c-'0';
  18. c=getchar();
  19. }
  20. return w;
  21. }
  22. void insert(int x,int y)
  23. {
  24. t++;
  25. ver[t]=y;
  26. nxt[t]=head[x];
  27. head[x]=t;
  28. d[y]++;
  29. }
  30. bool check(int x,int y)
  31. {
  32. if(y==0||y==cnt+1) return 0;
  33. if(x<y) y--;
  34. return l[x]<=pos[y]&&pos[y]<=r[x];//钥匙是否在当前可达区间中
  35. }
  36. void toposort()
  37. {
  38. queue<int> q;
  39. for(int i=1;i<=cnt;i++){
  40. if(d[i]==0) q.push(i);
  41. }
  42. while(!q.empty()){
  43. int x=q.front();
  44. q.pop();
  45. bool flag=1;
  46. while(flag){
  47. flag=0;
  48. while(check(x,l[x]-1)) l[x]=l[l[x]-1],flag=1;//可以就更新为左边的左端点
  49. while(check(x,r[x]+1)) r[x]=r[r[x]+1],flag=1;//更新为右边的右端点
  50. }
  51. for(int i=head[x];i;i=nxt[i]){
  52. int y=ver[i];
  53. d[y]--;
  54. if(d[y]==0) q.push(y);
  55. }
  56. }
  57. }
  58. int main()
  59. {
  60. n=read();m=read();q=read();
  61. for(i=1;i<=m;i++){
  62. x[i]=read();y[i]=read();
  63. lock[x[i]]=1;
  64. }
  65. lock[n]=1;
  66. for(i=1;i<=n;i++){
  67. gap[i]=cnt;
  68. if(lock[i]){
  69. l[cnt]=r[cnt]=cnt;
  70. cnt++;
  71. }
  72. }
  73. cnt--;
  74. for(i=1;i<=m;i++){
  75. int tx=gap[x[i]],ty=gap[y[i]];
  76. pos[tx]=ty;
  77. if(ty<=tx) insert(tx+1,tx);
  78. else insert(tx,tx+1);
  79. }
  80. toposort();
  81. for(i=1;i<=q;i++){
  82. int x=read(),y=read();
  83. x=gap[x],y=gap[y];
  84. if(l[x]<=y&&y<=r[x]) puts("YES");
  85. else puts("NO");
  86. }
  87. return 0;
  88. }

[洛谷P4436] HNOI/AHOI2018 游戏的更多相关文章

  1. [Bzoj5285][洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)

    P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生 ...

  2. 【题解】Luogu P4436 [HNOI/AHOI2018]游戏

    原题传送门 \(n^2\)过百万在HNOI/AHOI2018中真的成功了qwqwq 先将没门分格的地方连起来,枚举每一个块,看向左向右最多能走多远,最坏复杂度\(O(n^2)\),但出题人竟然没卡(建 ...

  3. 洛谷P4424 [HNOI/AHOI2018]寻宝游戏(思维题)

    题意 题目链接 Sol 神仙题Orz Orz zbq爆搜70.. 考虑"与"和"或"的性质 \(0 \& 0 = 0, 1 \& 0 = 0\) ...

  4. 洛谷P4438 [HNOI/AHOI2018]道路(dp)

    题意 题目链接 Sol 每当出题人想起他出的HNOI 2018 Day2T3,他都会激动的拍打着轮椅 读题比做题用时长系列... \(f[i][a][b]\)表示从根到\(i\)的路径上,有\(a\) ...

  5. 洛谷P4425 [HNOI/AHOI2018]转盘(线段树)

    题意 题目链接 Sol 首先猜一个结论:对于每次询问,枚举一个起点然后不断等到某个点出现时才走到下一个点一定是最优的. 证明不会,考场上拍了3w组没错应该就是对的吧... 首先把数组倍长一下方便枚举起 ...

  6. Luogu P4436 [HNOI/AHOI2018]游戏

    题目 我们要求出\(l_i,r_i\)表示\(i\)最远能够到达的最左边和最右边的格子. 首先有一个比较简单的暴力,就是每次我们选择一个格子,然后从当前格子开始往左右暴力扩展,找到能够到达的最远的格子 ...

  7. 洛谷 P4437 [HNOI/AHOI2018]排列(贪心+堆,思维题)

    题面传送门 开始 WA ycx 的遗产(bushi 首先可以将题目转化为图论模型:\(\forall i\) 连边 \(a_i\to i\),然后求图的一个拓扑序 \(b_1,b_2,\dots b_ ...

  8. 洛谷 P4426 - [HNOI/AHOI2018]毒瘤(虚树+dp)

    题面传送门 神仙虚树题. 首先考虑最 trival 的情况:\(m=n-1\),也就是一棵树的情况.这个我相信刚学树形 \(dp\) 的都能够秒掉罢(确信).直接设 \(dp_{i,0/1}\) 在表 ...

  9. 洛谷P1118 数字三角形游戏

    洛谷1118 数字三角形游戏 题目描述 有这么一个游戏: 写出一个1-N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直 ...

随机推荐

  1. 如何比较两个txt文件内容的细微差别

    如何比较两个txt文件内容的细微差别 https://jingyan.baidu.com/article/19020a0a1dd04a529c284272.html 听语音 | 浏览:3500 | 更 ...

  2. Nil Channels Always Block(Go语言中空管道总是阻塞)

    译自:https://www.godesignpatterns.com/2014/05/nil-channels-always-block.html 原作者:Alex Lockwood 在本篇文章中, ...

  3. ES6标准入门 第五章:数值的扩展

    1.二进制和八进制数值表示法 二进制前缀:0b(或0B):   八进制前缀:0o(或0O). 注意:ES5的严格模式 和 ES6中不再允许使用 0  表示八进制. 将二进制和八进制数值转换为十进制数值 ...

  4. CSS3——背景 文本 字体 链接 列表样式 表格

    背景 background-color rgb(255,0,0,1)      最后一个值表示透明度,范围是 0--1 background-image 默认平铺重复显示 background-rep ...

  5. numpy 介绍和基础使用详解

    NUMPY INTRODUCTION NUMPY 提供了一个在Python中做科学计算的基础库,重在数值计算,主要用于处理多维数组,用于储存和处理大型矩阵,本身是由C语言开发,比python自身的列表 ...

  6. ARP协议基础

    ARP 什么是ARP协议 ARP协议是能够根据IP地址解析出该IP地址所在设备的MAC地址,叫(Address Resolution Protocol)地址解析协议 ARP地址的工作流程 当一台主机A ...

  7. CSS中BFC规则

    何为BFC BFC(Block formatting context)直译为"块级格式化上下文".它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的B ...

  8. [LeetCode] 45. 跳跃游戏 II

    题目链接 : https://leetcode-cn.com/problems/jump-game-ii/ 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位 ...

  9. Spring KafkaTemplate 注解式实现 工厂模式

    实现注解式注入kafkaTemplate 生产者和消费者,简化配置文件 目录 消费者工厂 /** * 消费者工厂 */ @EnableKafka @Configuration public class ...

  10. kotlin学习(6)运算符重载和其他约定

    约定 在Kotlin中,可以调用自己代码中定义的函数,来实现语言结构.这戏功能与特定的函数命名相关,例如,在你的类中定义了一个名为plus的特殊方法,那么按照约定,就可以在该类的实例上使用 + 运算符 ...