[HNOI/AHOI2018]游戏,第三次模拟赛,暴力+优化?玄学

正题

      [HNOI/AHOI2018]游戏

      我们可以知道,两道门之间的点可以到达的区域是一样的,所以我们可以使两道门之间的点变为一个区间,然后它询问什么,我们就做什么。

      每个区间拼命往外拓,我们知道,区间的左右两边都是门,所以左右两边都有一个区间,那么当且仅当它们的门的钥匙在当前的区间内,才能拓展区间。

      很容易可以知道,我们把一个区间拉进当前区间,说明那个区间能遍历到的点当前区间也能遍历到,所以更新当前区间的最左端点和最右端点即可。

#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");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值