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. NMS和soft-nms算法

    非极大值抑制算法(nms) 1. 算法原理 非极大值抑制算法(Non-maximum suppression, NMS)的本质是搜索局部极大值,抑制非极大值元素. 2. 3邻域情况下NMS的实现 3邻 ...

  2. linux源码Makefile详解(完整)

    转自:http://www.cnblogs.com/Daniel-G/p/3286614.html 随着 Linux 操作系统的广泛应用,特别是 Linux 在嵌入式领域的发展,越来越多的人开始投身到 ...

  3. crontab定时作业

    crontab用于在指定时间执行某项作业,如执行脚本或命令. 1.crontab -e      创建一个crontab文件,并添加作业(这个crontab的拥有者是创建者). 这里要注意:必须指定s ...

  4. navicat报caching_sha2_password异常

    使用navicat连接mysql报错(升级到mysql8版本时的错) 解决办法: 通过命令行登录mysql后, 输入: alter user 'root'@'localhost' IDENTIFIED ...

  5. java.util.Map

    map时key/value形式存储信息的,键可以为对象null public static void main(String[] args) { Map<String, String> m ...

  6. POJ 3243 // HDU 2815(改下输出,加个判断)

    A^x = B (mod C) 的模板题,不够要用扩展BSGS (虽然AC,但完全理解不了模板0.0,以后学好数学在来慢慢理解555555) #include <iostream> #in ...

  7. Android Studio 超级简单的打包生成apk

    为什么要打包: apk文件就是一个包,打包就是要生成apk文件,有了apk别人才能安装使用.打包分debug版和release包,通常所说的打包指生成release版的apk,release版的apk ...

  8. python 全栈开发,Day123(图灵机器人,web录音实现自动化交互问答)

    昨日内容回顾 . 百度ai开放平台 . AipSpeech技术,语言合成,语言识别 . Nlp技术,短文本相似度 . 实现一个简单的问答机器人 . 语言识别 ffmpeg (目前所有音乐,视频领域,这 ...

  9. 步步为营-59-svn简介

    说明:版本控制器Svn的使用,安装教程不再多说 VisualSVN-Server--项目经理 TortoiseSVN--右击的时候显示 VisualSVN-- visual studio中使用 1 搭 ...

  10. STL算法之函数copy

    STL算法之copy copy(beg, end, dest) #include <iostream> #include <algorithm> #include <ve ...