• LOJ #2508. 「AHOI / HNOI2018」游戏 拓扑排序


    好神仙的一道题!   

    由于每个门对应的钥匙仅有一把,所以我们可以确定门和门之间的相对解锁顺序.   

    比如,解锁门 $(x,x+1)$ 的要是在 $[1,x]$ 之间的话 $x+1$ 无论如何也到不了 $x$ 这一侧,但是 $x$ 有可能可以到达 $x+1$ 这边. 

    所以我们就先去解锁 $x+1$,然后再去解锁 $x$,这样的话 $x$ 就可以直接继承 $x+1$ 的拓展结果了.      

    code:   

    #include <bits/stdc++.h>   
    #define ll long long 
    #define N 1000200 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int edges=1; 
    int hd[N],to[N<<1],nex[N<<1],deg[N];     
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;       
        deg[v]++;  
    }
    int n,m,Q,p[N],tot,key[N]; 
    queue<int>q;  
    void topo() 
    {
        int i,j;  
        for(i=n;i;--i)  if(!deg[i])  q.push(i);    
        while(!q.empty()) 
        {
            int u=q.front(); q.pop();   p[++tot]=u;    
            for(int i=hd[u];i;i=nex[i])   
            {
                int v=to[i];   
                --deg[v];  
                if(!deg[v])   
                    q.push(v);   
            }
        }
    } 
    int L[N],R[N];    
    void cal(int x) 
    {
        int l=x,r=x;   
        while(1) 
        {
            int pl=l,pr=r;   
            while(l>1&&(!key[l-1]||(l<=key[l-1]&&key[l-1]<=r)))   
                l=L[l-1];   
            while(r<n&&(!key[r]||(l<=key[r]&&key[r]<=r)))   
                r=R[r+1];      
            if(l==pl&&r==pr)   
                break;     
        }
        L[x]=l,R[x]=r;   
    }
    int main() 
    { 
        //  setIO("input");  
        int i,j;  
        scanf("%d%d%d",&n,&m,&Q);   
        for(i=1;i<=m;++i) 
        {
            int x,y;  
            scanf("%d%d",&x,&y);  
            key[x]=y;   
            if(y<=x)   
                add(x+1,x);   
            else 
                add(x,x+1);  
        }
        topo();      
        for(i=1;i<=n;++i) 
            L[i]=R[i]=i;   
        for(i=1;i<=n;++i)   
            cal(p[i]);   
        while(Q--) 
        {
            int s,t; 
            scanf("%d%d",&s,&t);    
            if(L[s]<=t&&t<=R[s])   
                printf("YES
    ");  
            else 
                printf("NO
    ");  
        }
        return 0; 
    }
    

      

  • 相关阅读:
    快速排序
    jenkins 升级
    JAVA中的Random()函数
    拦截器
    两个链表合并不加入新的链表空间
    统计字符 比如aaabbcca----3a2b1c1a
    折半查找两种实现
    字符串偏移
    java值传递
    基于zookeeper实现配置集中管理【转】
  • 原文地址:https://www.cnblogs.com/guangheli/p/12459948.html
Copyright © 2020-2023  润新知