正题
我们可以知道,两道门之间的点可以到达的区域是一样的,所以我们可以使两道门之间的点变为一个区间,然后它询问什么,我们就做什么。
每个区间拼命往外拓,我们知道,区间的左右两边都是门,所以左右两边都有一个区间,那么当且仅当它们的门的钥匙在当前的区间内,才能拓展区间。
很容易可以知道,我们把一个区间拉进当前区间,说明那个区间能遍历到的点当前区间也能遍历到,所以更新当前区间的最左端点和最右端点即可。
#include<cstdio>
#include<cstdlib>
#include<cstring>
int min(int x,int y){
return x<y?x:y;
}
int max(int x,int y){
return x>y?x:y;
}
int tf[1000010];
int n,m,p;
int tot=0;
int where[1000010];
bool find[1000010];
int l[1000010],r[1000010];
bool findip(int x,int y){
if(find[where[x]]) return l[where[x]]<=y && y<=r[where[x]];
find[where[x]]=true;
int ll=l[where[x]],rr=r[where[x]];
while(1){
bool qq=false;
if(ll!=1 && ll<=tf[ll-1] && tf[ll-1]<=rr){
qq=true;
ll=min(l[where[ll-1]],ll);
rr=max(r[where[ll-1]],rr);
}
else if(rr!=n && ll<=tf[rr] && tf[rr]<=rr){
qq=true;
ll=min(l[where[rr+1]],ll);
rr=max(r[where[rr+1]],rr);
}
if(!qq) break;
}
l[where[x]]=ll,r[where[x]]=rr;
return l[where[x]]<=y && y<=r[where[x]];
}
int main(){
scanf("%d %d %d",&n,&m,&p);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d %d",&x,&y);
tf[x]=y;
}
int now=1;
while(now<=n){
tot++;
l[tot]=r[tot]=now;
where[now]=tot;
while(tf[now]==0 && now+1<=n){
now++;
where[now]=tot;
r[tot]=now;
}
now++;
}
// random_shuffle(p+1,p+n+1);
for(int i=1;i<=p;i++){
int x,y;
scanf("%d %d",&x,&y);
if(findip(x,y)) printf("YES\n");
else printf("NO\n");
}
}