BZOJ5288 [Hnoi2018]游戏

BZOJ5288 [HNOI/AHOI2018]游戏

题目看这里

题解

对于20分,我们可以暴力搞,往返跑,反正怎么都能过。
对于\(x<=y\)的40分的点,就是网上熟悉的倒着跑,就可以AC的做法。
对于一个点,我们处理出它左右可以到达的最大区间。对于这个特殊性质,我们很容易的想到从后往前跑,因为打开它的钥匙一定在前面,那么我们每次访问一个点,跳到它后面序号比它大的那个点的最右区间,看是否能往前扩展,这样每个点的遍历就是\(O(n)\)的了。
然而出题人据说为了卡另一种情况,没卡这一个。

对于满分做法。(口胡的,玄学多好啊
考虑一下对于60分的贪心,我们发现。
因为是从后到前,所以我们不会重复的去处理区间,以此来达到\(O(n)\)
对于满分,我们也是这样处理,
为了不重复处理区间,对于满分,我们考虑一下拓扑排序,为什么?
我们考虑这样建边,如果钥匙在当前门的左边,\(add(i+1,i)\),右边,\(add(i,i+1)\),表示我们当前无法走到这边,那么我们就可以从底层开始处理出小区间,以此拓展,每个点不会重复访问,时间复杂度为\(O(n)\)
调了我一晚上qwq,发现一个问题,对于入队,我们优先序号大的会快不少,原因是出题人造的数据基本门和钥匙相等,其实按照这样的建边规则,因为是优先区间小的,然后更新大的,所以其实拓扑的时候还是要记录一下的?

Code

Ps:这个代码是我在洛谷题解上看的,问题很大,但是过了。。。
魔改了一天,想清楚了还是要记录每个点然后在一个一个向上更新,算了不改了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e6+5;
queue<int>q;
int n,m,T,id[N];
int key[N],l[N],r[N],in[N];
int num,head[N];
struct node{
	int to,nex;
}e[N<<1];
int read(){
	int x=0,w=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*w;
}

void add(int from,int to){
	num++;
	e[num].to=to;
	e[num].nex=head[from];
	head[from]=num;
}

int main(){
	n=read();m=read();T=read();
	for(int i=1;i<=m;i++){
		int x=read(),y=read();key[x]=y;
		if(x>=y)add(x+1,x),in[x]++;else add(x,x+1),in[x+1]++;
	}
	for(int i=n;i>=1;i--){
		if(!key[i]&&i!=n)id[i]=id[i+1],l[id[i]]=i;
		else l[i]=i,r[i]=i,id[i]=i;
	}
	for(int i=1;i<=n;i++){
		l[i]=l[id[i]];r[i]=r[id[i]];
	}
	for(int i=n;i>=1;i--)if(!in[i])q.push(i);
	while(!q.empty()){
		int u=q.front(),f=1;q.pop();
		for(int i=head[u];i;i=e[i].nex){
			{in[e[i].to]--;if(!in[e[i].to])q.push(e[i].to);}
		}
		while(f){
			f=0;
		while(l[u]>1&&(!key[l[u]-1]||(key[l[u]-1]>=l[u]&&key[l[u]-1]<=r[u])))
				l[u]=l[l[u]-1],f=1;
			while(r[u]<n&&(!key[r[u]]||(key[r[u]]>=l[u]&&key[r[u]]<=r[u])))
				r[u]=r[r[u]+1],f=1;
		}
	
	}
	while(T--){
		int x=read(),y=read(); 
		if(l[x]<=y&&r[x]>=y)
			printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}
posted @ 2019-02-16 17:06  Epiphyllum_thief  阅读(123)  评论(0编辑  收藏  举报