[HNOI/AHOI2018]游戏

Description:

一次小G和小H在玩寻宝游戏,有n个房间排成一列,编号为\(1,2,...,n\),相邻的房间之间都有一道门。其中一部分们上锁(因此需要有对应的钥匙才能开门),其余的门都能直接打开。现在小G告诉了小H每把锁的钥匙在哪个房间里(每把锁锁有且只有一把钥匙与之对应),并作出p次指示:第i次让小H从第\(S_i\)个房间出发到\(T_i\)个房间里。但是小G有时会故意在指令中放入死路,而小H也不想浪费多余的体力去尝试,于是想事先调查清楚每次的指令是否会存在一条通路。

Hint:

\(n,m,q \le 10^6\)

Solution:

每次直接在一个点暴力向两边拓展,但这样会被卡,随机化就行了

(然而不随机化,就是倒着跑还快一点,数据666)

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=2e6+5;
int n,m,q,cnt,hd[mxn];
int a[mxn],b[mxn],L[mxn],R[mxn];

inline int read() {
	char c=getchar(); int x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(int &x,int y) {if(x>y) x=y;}

struct ed {
	int to,nxt;
}t[mxn<<1];

inline void add(int u,int v) {
	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void expand(int x) {
	int l=x,r=x;
	while(1) {
		int flag=0;
		if(l>1&&((l<=a[l-1]&&a[l-1]<=r)||!a[l-1])) 
			flag=1,--l,l=min(l,L[l]),r=max(r,R[l]);
		if(r<n&&((l<=a[r]&&a[r]<=r)||!a[r])) 
			flag=1,++r,l=min(l,L[r]),r=max(r,R[r]);
		if(!flag) break;	
	}
	L[x]=l,R[x]=r;
}

int main()
{
	n=read(); m=read(); q=read(); int x,y;
	for(int i=1;i<=m;++i) {
		x=read(); y=read();
		a[x]=y;
	}
	for(int i=1;i<=n;++i) L[i]=n+1,R[i]=0,b[i]=i;
	random_shuffle(b+1,b+n+1);
	for(int i=1;i<=n;++i) expand(b[i]);
	while(q--) {
		x=read(); y=read();
		if(L[x]<=y&&y<=R[x]) puts("YES");
		else puts("NO");
	}
    return 0;
}

posted @ 2019-03-22 22:26  cloud_9  阅读(242)  评论(0编辑  收藏  举报