好神仙的一道题!
由于每个门对应的钥匙仅有一把,所以我们可以确定门和门之间的相对解锁顺序.
比如,解锁门 $(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\n");
else
printf("NO\n");
}
return 0;
}