[HNOI/AHOI2018]游戏

题目链接

https://loj.ac/problem/2508
https://www.lydsy.com/JudgeOnline/problem.php?id=5288
https://www.luogu.org/problemnew/show/P4436

思路

离散化没啥好说的
一堵墙
左边是i,右边是i+1
如果钥匙在墙的左边,那么右边永远过不去左边(拿不到钥匙)
那就右边向左边连边
就是先处理左边,等全部处理完了再去处理右边
然后拓扑上面暴力弄就好了
听着好像分治呀

吐槽

不过这数据好垃圾呀,随机处理也可以过
我写错了代码还90、、、

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+7;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int n,js,m,p,hav[N],belong[N],wall[N],L[N],R[N],ru[N],q[N];
struct node {
    int v,nxt;
}e[N];
int head[N],tot;
inline void add(int u,int v) {
    // cout<<u<<" "<<v<<" !\n";
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
inline int max(int a,int b) {return a>b?a:b;}
inline int min(int a,int b) {return a>b?b:a;}
int main() {
    // freopen("game8.in","r",stdin);
    // freopen("a.out","w",stdout);
    n=read(),m=read(),p=read();
    for(int i=1;i<=m;++i) hav[read()]=read();
    js=1;
    for(int i=1,l=1,r=1;i<=n;++i) {
        belong[i]=js;
        if(hav[i]) js++;
    }
    js=belong[n];
    for(int i=1;i<=n;++i) {
        if(hav[i]) {
            wall[belong[i]]=belong[hav[i]];
            if(hav[i]>i) add(belong[i],belong[i+1]),ru[belong[i+1]]++;
            else add(belong[i+1],belong[i]),ru[belong[i]]++;
            // cout<<x<<" "<<y<<"<\n";
        }
    }
    for(int i=1;i<=js;++i) {
        L[i]=R[i]=i;
        if(!ru[i]) q[++q[0]]=i;
    }
    int mmp=0;
    while(q[0]) {
        int u=q[q[0]];
        q[0]--;
        // cout<<u<<"  <<<<<<u\n";
        for(int i=head[u];i;i=e[i].nxt) {
            int v=e[i].v;
            // cout<<u<<" -> " <<v<<"\n";
            ru[v]--;
            while (233) {
                int flag=true;
                while (L[v] <= wall[R[v]] && wall[R[v]] <= R[v] && R[v]<=js) {
                    flag=false;
                    L[v]=min(L[v],L[R[v]+1]);
                    R[v]=max(R[v],R[R[v]+1]);
                }
                while (L[v] <= wall[L[v] - 1] && wall[L[v] - 1] <= R[v] && L[v] > 1) {
                    flag=false;
                    L[v]=min(L[v],L[L[v]-1]);
                    R[v]=max(R[v],R[L[v]-1]);
                }
                if(flag) break;
            }
            if(!ru[v]) q[++q[0]]=v;
        }
    }
    // for(int i=1;i<=js;++i) cout<<L[i]<<" "<<R[i]<<"<\n";
    for(int i=1;i<=p;++i) {
        int S=read(),T=read();
        if(L[belong[S]]<=belong[T]&&belong[T]<=R[belong[S]]) puts("YES");
        else puts("NO");
    }
    return 0;
}
全部评论

相关推荐

11-18 15:57
门头沟学院 Java
最终归宿是测开:这个重邮的大佬在重邮很有名的,他就喜欢打92的脸,越有人质疑他,他越觉得爽😂
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务