AtCoder Regular Contest 076E Connected? 栈

版权声明:转吧转吧这条东西只是来搞笑的。。 https://blog.csdn.net/jpwang8/article/details/88992059

Description


N*M的矩阵里面有k对不同颜色的点,同颜色的点之间互相连边,问所有的边是否能不相交
k 1 0 5 k\le10^5

Solution


首先因为边是可以随便拉扯的,因此很容易想到不合法的情况当且仅当两对点都在边界上,并且且它们相交

考虑把一条边拆成两个点,我们按照顺时针方向依次遍历这些点。一条边中的第一次出现的点入栈,第二次出现就出栈。那么不合法的情况就是一条边已经出栈了,它的两个点之间仍有未出栈的点。

一个比较牛逼的做法就是我们给每条边随机一个权值,那么就可以用前缀异或和来搞定这个“是否所有数字出现了恰好两次”的问题了

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fi first
#define se second

typedef std:: pair <int,int> pair;
const int N=2000005;

std:: vector <pair> p[4];

int ins[N],out[N],s[N],r[N],tot;
int n,m,k;

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void get(int i,int x,int y) {
	if (!x) p[0].push_back(pair(y,i));
	else if (y==m) p[1].push_back(pair(x,i));
	else if (x==n) p[2].push_back(pair(y,i));
	else p[3].push_back(pair(x,i));
}

int main(void) {
	n=read(),m=read(),k=read();
	rep(i,1,k) {
		int x1=read(),y1=read(),x2=read(),y2=read();
		if ((!x1||x1==n||!y1||y1==m)&&(!x2||x2==n||!y2||y2==m)) {
			get(i,x1,y1),get(i,x2,y2);
		}
		r[i]=1LL*rand()*rand()+1;
	}
	rep(i,0,3) std:: sort(p[i].begin(),p[i].end());
	rep(j,0,1) {
		for (int i=0;i<p[j].size();++i) {
			int x=p[j][i].se; ++tot;
			s[tot]=s[tot-1]^r[x];
			if (!ins[x]) ins[x]=tot;
			else out[x]=tot;
		}
	}
	rep(j,2,3) {
		std:: reverse(p[j].begin(),p[j].end());
		for (int i=0;i<p[j].size();++i) {
			int x=p[j][i].se; ++tot;
			s[tot]=s[tot-1]^r[x];
			if (!ins[x]) ins[x]=tot;
			else out[x]=tot;
		}
	}
	rep(i,1,k) {
		if (out[i]<ins[i]) std:: swap(out[i],ins[i]);
		if (s[ins[i]-1]!=s[out[i]]) {
			puts("NO"); return 0;
		}
	}
	puts("YES");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/88992059