scarlyw的博客

如果世界真的不喜欢你,那世界就是我的敌人了。

NOI模拟(5.8) HNOID2T1 游戏 (bzoj5288)

游戏

题目背景:

5.8 模拟 HNOI2018D2T1  

分析:拓扑排序

 

这道题好神啊我不会······考场上打了60分暴力,被卡成40,其他人不管是乱搞还是正解,还是什么奇奇怪怪的玄学都过了,感觉内心崩溃,直接说正解吧,考虑一扇门,如果钥匙在左边,那么显然只能从左边才可能到右边,并且,如果左边可以到右边那么右边的可以到的区间,左边的一定也可以到,那么我们应该先处理右边,然后之后在判断左边是否能到右边,那么我们就可以根据这个关系直接按照一个拓扑序来处理对应点能够到达的区间,然后每次判断能否扩展,就可以了,比较显然的是,一个节点显然只会从左边扩展一次,从右边扩展一次,被当做停止节点多次,但是显然停止节点总次数是O(n),所以,总复杂度是O(n)

 

Source:

 

/*
    created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <ctime>
#include <bitset>
  
inline char read() {
    static const int IN_LEN = 1024 * 1024;
    static char buf[IN_LEN], *s, *t;
    if (s == t) {
        t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
        if (s == t) return -1;
    }
    return *s++;
}
  
///*
template<class T>
inline void R(T &x) {
    static char c;
    static bool iosig;
    for (c = read(), iosig = false; !isdigit(c); c = read()) {
        if (c == -1) return ;
        if (c == '-') iosig = true; 
    }
    for (x = 0; isdigit(c); c = read()) 
        x = ((x << 2) + x << 1) + (c ^ '0');
    if (iosig) x = -x;
}
//*/
 
const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN];
char *oh = obuf;
inline void write_char(char c) {
    if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
    *oh++ = c;
}
 
 
template<class T>
inline void W(T x) {
    static int buf[30], cnt;
    if (x == 0) write_char('0');
    else {
        if (x < 0) write_char('-'), x = -x;
        for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
        while (cnt) write_char(buf[cnt--]);
    }
}
 
inline void flush() {
    fwrite(obuf, 1, oh - obuf, stdout), oh = obuf;
}
  
/*
template<class T>
inline void R(T &x) {
    static char c;
    static bool iosig;
    for (c = getchar(), iosig = false; !isdigit(c); c = getchar())
        if (c == '-') iosig = true; 
    for (x = 0; isdigit(c); c = getchar()) 
        x = ((x << 2) + x << 1) + (c ^ '0');
    if (iosig) x = -x;
}
//*/
 
inline void write(bool flag) {
    if (flag) write_char('Y'), write_char('E'), 
        write_char('S'), write_char('\n');
    else write_char('N'), write_char('O'), write_char('\n');
}
 
const int MAXN = 1000000 + 10;
 
int n, m, t, x, y, cnt;
int l[MAXN], r[MAXN], id[MAXN], pos[MAXN], p[MAXN], deg[MAXN];
bool left[MAXN], right[MAXN];
 
inline void solve() {
    R(n), R(m), R(t);
    for (int i = 1; i <= m; ++i) R(x), R(y), pos[x] = y;
    id[1] = cnt = 1;
    for (int i = 2; i <= n; ++i) id[i] = (!pos[i - 1]) ? cnt : ++cnt;
    cnt = 0;
    for (int i = 1; i <= n; ++i) {
        if (pos[i] != 0) {
            if (pos[i] > i) left[id[i + 1]] = true, deg[id[i + 1]]++;
            else right[id[i]] = true, deg[id[i]]++;
            p[++cnt] = id[pos[i]];
        }
    }
    cnt++;
    static int q[MAXN];
    int head = 0, tail = 0;
    for (int i = 1; i <= cnt; ++i) if (deg[i] == 0) q[++tail] = i;
    while (head < tail) {
        int cur = q[++head];
        if (cur != 1 && left[cur] == false) 
            if (--deg[cur - 1] == 0) q[++tail] = cur - 1;
        if (cur != cnt && right[cur] == false)
            if (--deg[cur + 1] == 0) q[++tail] = cur + 1;
    }
    for (int i = 1; i <= cnt; ++i) {
        int cur = q[i];
        bool flag = true;
        l[cur] = r[cur] = cur;
        while (flag) {
            flag = false;
            while (left[cur] && p[l[cur] - 1] >= l[cur] && 
                p[l[cur] - 1] <= r[cur]) l[cur] = l[l[cur] - 1], flag = true;
            while (right[cur] && p[r[cur]] >= l[cur] && 
                p[r[cur]] <= r[cur]) r[cur] = r[r[cur] + 1], flag = true;
        }
    }
    while (t--) R(x), R(y), x = id[x], y = id[y], write(y >= l[x] && y <= r[x]);
}
 
int main() {
    //freopen("in.in", "r", stdin);
    solve();
    flush();
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/scar_lyw/article/details/80258882
文章标签: NOI 拓扑排序
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

NOI模拟(5.8) HNOID2T1 游戏 (bzoj5288)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭