5288: [Hnoi2018]游戏

链接

分析:

  考虑y<=x的怎么做,那么只能从左边走到右边。我们可以从最右边的点开始,一次确定每个点往右边可以走多少。

  L[x],R[x]分别是x向左向右最远走到的位置,初始L[x]=x,R[x]=x。R[n]=n,然后看n-1,如果n-1存在打开n-1这扇门的钥匙,那么说明n-1可以到n,相应的R[n-1]=R[n]。同样的考虑i,如果i可以打开第i扇门,那么R[i]=R[i+1],继续判断如果i可以打开第R[i]扇门,那么R[i]=R[R[i]]……

  于是这样可以求出每个往右延伸的范围。复杂度的证明:每扇门只会被打开一次,每个点只会被求扫一次,于是复杂度是$O(n)$

  如果y不小于x,考虑怎么做。将两个点之间的边确定方向(如果钥匙在左边,那么边是左->右,否则是右->左),然后对于找到一个点x,它既能向左走也可以向右走,从这个点开始,往左走到的是y,那么x->y这一段和y<=x的性质一样,做法也一样,扫一遍即可,往右走同理。最后处理x,直接暴力处理即可。

  复杂度:每个点只会存在于一条链中,暴力处理的点总复杂度是O(n)的。

  如果一条边上没有门呢?没法定向了,缩点即可。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
int a[N], b[N];
int n, m, Q; namespace BF1{
int L[], R[]; bool vis[]; vector<int> vec[], d;
void Mark(int x) {
for (int j = ; j < (int)vec[x].size(); ++j) vis[vec[x][j]] = ;
}
void Calc(int x) {
L[x] = R[x] = x;
for (int i = ; i <= n; ++i) vis[i] = ;
for (int i = ; i < (int)d.size(); ++i)
vis[d[i]] = ;
Mark(x);
while () {
if (!vis[R[x]] && !vis[L[x] - ]) break;
if (vis[R[x]]) {
R[x] ++; Mark(R[x]);
}
if (vis[L[x] - ]) {
L[x] --; Mark(L[x]);
}
}
}
void Main() {
for (int i = ; i <= m; ++i) vec[b[i]].push_back(a[i]);
for (int i = ; i <= m; ++i) vis[a[i]] = ;
for (int i = ; i < n; ++i) if (!vis[i]) d.push_back(i);
for (int i = ; i <= n; ++i) Calc(i);
while (Q--) {
int s = read(), t = read();
if (L[s] <= t && t <= R[s]) puts("YES");
else puts("NO");
}
}
} int head[N], fa[N], vis[N], chu[N], nxt[N], pre[N], L[N], R[N], pos[N], En;
vector<int> d;
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
inline void Union(int x,int y) { if (x != y) fa[y] = x;}
inline void add_edge(int x,int y) { x = find(x), y = find(y); chu[x] ++; } void Calc(int x) {
int z = x;
while (z >= && chu[z] != ) z = pre[z]; if (z < ) z = nxt[z];
for (int i = z; i <= x; i = nxt[i]) {
L[i] = i;R[i] = i;
int now = pre[L[i]];
if (now < z) continue;
while (L[i] <= pos[now] && pos[now] <= R[i]) {
L[i] = L[now], now = pre[L[i]];
}
}
z = x;
while (z <= n && chu[z] != ) z = nxt[z]; if (z > n) z = pre[z];
for (int i = z; i >= x; i = pre[i]) {
L[i] = i;R[i] = i;
int now = R[i];
if (nxt[now] > z) continue;
while (L[i] <= pos[now] && pos[now] <= R[i]) {
R[i] = R[nxt[now]], now = R[i];
}
}
while () {
bool f = ;
if (L[x] <= pos[R[x]] && pos[R[x]] <= R[x]) R[x] = nxt[R[x]], f = ;
if (L[x] <= pos[pre[L[x]]] && pos[pre[L[x]]] <= R[x]) L[x] = pre[L[x]], f = ;
if (!f) break;
}
}
void solve() {
for (int i = ; i <= m; ++i) vis[a[i]] = ;
for (int i = ; i <= n; ++i) fa[i] = i;
for (int i = ; i < n; ++i) if (!vis[i]) Union(i, i + );
int last = ;
for (int i = ; i <= n; ++i)
if (find(i) == i) pre[i] = last, nxt[last] = i, last = i;
nxt[last] = n + ; pre[n + ] = last; for (int i = ; i <= m; ++i) {
a[i] = find(a[i]), b[i] = find(b[i]);
if (b[i] <= a[i]) add_edge(a[i], nxt[a[i]]);
else add_edge(nxt[a[i]], a[i]);
pos[a[i]] = b[i];
}
for (int i = ; i <= n; i = nxt[i]) {
if (chu[i] == || (i == nxt[] && chu[i] == ) || (i == pre[n + ] && chu[i] == ))
Calc(i);
}
}
int main() {
n = read(), m = read(), Q = read();
for (int i = ; i <= m; ++i)
a[i] = read(), b[i] = read();
if (n <= && m <= ) { BF1::Main(); return ; }
if (m == ) { while (Q --) puts("YES"); return ; }
solve();
for (int i = ; i <= n; ++i) if (!L[i]) L[i] = L[find(i)];
for (int i = n; i >= ; --i) if (R[i]) R[i] = nxt[R[i]] - ;
for (int i = ; i <= n; ++i) if (!R[i]) R[i] = R[find(i)]; while (Q--) {
int s = read(), t = read();
if (L[s] <= t && t <= R[s]) puts("YES");
else puts("NO");
}
return ;
}

  

代码:

5288: [Hnoi2018]游戏的更多相关文章

  1. bzoj 5288: [Hnoi2018]游戏

    Description Solution 乱搞能A的题,毁我青春 记忆化一下扩展过程 只要不是从 \(1\) 枚举到 \(n\) 去扩展都可以 \(AC\) 于是 \(random\_shuffle\ ...

  2. 【BZOJ5288】[HNOI2018]游戏(拓扑排序)

    [BZOJ5288][HNOI2018]游戏(拓扑排序) 题面 BZOJ 洛谷 题解 去年省选的时候这题给我乱搞整过去整过去了,也是虐心了.... 所以当然是来讲正儿八经的正确做法啦. 很明显,我们需 ...

  3. BZOJ.5288.[AHOI/HNOI2018]游戏(思路 拓扑)

    BZOJ LOJ 洛谷 考虑如何预处理每个点能到的区间\([l,r]\). 对于\(i,i+1\)的一扇门,如果钥匙在\(i\)的右边,连边\(i\to i+1\),表示从\(i\)出发到不了\(i+ ...

  4. 【BZOJ5288】[HNOI2018]游戏(乱搞?)

    [BZOJ5288][HNOI2018]游戏(乱搞?) 题面 BZOJ 洛谷 题面自己到洛谷上看把 题解 考场上乱搞拿到了\(90\)分,简直不敢相信. 回家把代码再交了一份直接就\(AC\)了??? ...

  5. [HNOI2018]游戏[拓扑排序]

    题意 题目链接 分析 先将没有锁的房间缩点,首先有一个 \(O(n^2)\) 的想法:从每个点出发,每次检查能否向两边扩张. 容易发现门和门之间如果有锁,必然只有一方能够开锁(只有一把钥匙),并且能够 ...

  6. 【比赛】HNOI2018 游戏

    考试的时候线段树区间查询的return条件打成了l==r....于是光荣爆20(线段树都不会打了?) 看膜博士的题解 #include<bits/stdc++.h> #define ui ...

  7. [BZOJ5288][HNOI2018]游戏(拓扑排序)

    传送门:https://www.luogu.org/problemnew/show/P4436 20分的暴力加一个Random_shuffle就A了.我还能说什么.. 不过这个也不是毫无道理,复杂度应 ...

  8. bzoj5288: [Hnoi2018]游戏

    我还是太年轻了... 考场上就是直接枚举预处理当前位置左右延伸到的最远距离,好像是水了20.. 然后噶爷爷居然随机一下就AC了????mengbier #include<cstdio> # ...

  9. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

随机推荐

  1. freeRTOS中文实用教程6--错误排查

    1.前言 本章主要是为刚接触FreeRTOS 的用户指出那些新手通常容易遇到的问题.这里把最主要的篇幅放在栈溢出以及栈溢出侦测上 2.printf-stdarg.c 当调用标准C 库函数时,栈空间使用 ...

  2. 初识CPU卡、SAM卡/CPU卡简介、SAM卡简介 【转】

    初识CPU卡.SAM卡/CPU卡简介.SAM卡简介 IC卡按照接口方式可分为接触式卡.非接触式卡.复合卡:按器件技术可分为非加密存储卡.加密存储卡和CPU卡. 加密存储卡是对持卡人的认证,只有输入正确 ...

  3. 解决git: 'subtree' is not a git command. See 'git --help'.

    一.第一方法 git clone https://github.com/git/git.git cd git/contrib/subtree sudo make prefix=/usr sudo ma ...

  4. lnmp使用socket方式连接nginx优化php-fpm性能

    lnmp使用socket方式连接nginx优化php-fpm性能 Nginx连接fastcgi的方式有2种:TCP和unix domain socket 什么是Unix domain socket?- ...

  5. zabbix实现对tomcat的监控

    zabbix实现对tomcat的监控 工作原理 比如:当Zabbix-Server需要知道java应用程序的某项性能的时候,会启动自身的一个Zabbix-JavaPollers进程去连接Zabbix- ...

  6. Codeforces Round #Pi (Div. 2) C

    题意 : 给你一个序列,和 K ,选3 个数,下标严格递增, 满足 为递增的等比数列, 等比为K 思路 : 先统计所有数的个数,枚举等比数列的中间数 A, 计算 A 之后的 A*K的个数, A之前的 ...

  7. 前端组件库 - 搭建web app常用的样式/组件等收集列表(移动优先)

    0. 前端自动化(Workflow) 前端构建工具 Webpack - module bundler Yeoman - a set of tools for automating developmen ...

  8. JavaScript对象简介(一)

    本节介绍js的9个对象:Array数组对象 Boolean(true false) Date日前对象 Math 数学对象 Number 数字对象 String 字符串对象 RegExp 正则表达式对象 ...

  9. Inno Setup 系列之先卸载之后再安装

    需求使用Inno Setup打包程序之后,很多时候我们需要在安装文件之前卸载原有的程序而不是覆盖安装,本文的Code就是实现了这样的功能.如果想要在安装前先卸载,那么需要加下面代码,需要注意的是双星号 ...

  10. python 全栈开发,Day56(jQuery的ajax)

    昨日内容回顾 事件流: 1.事件捕获 从最外层到最内层 2.事件目标阶段 3.事件冒泡 从最内层到最外层 每个事件都会事件对象 event 属性和方法 属性: event.target 目标节点(冒泡 ...