题解洛谷 P8216【[THUPC2022 初赛] 画图】

大模拟,应该还算大模拟里面偏简单的。

正如官方题解说的,本题难点在于注意到这道题是可做题。

首先,一开始有 \(10^5\) 条线段,而 THUPC 只有 \(15\) 条,我们需要按照题意将“出现同方向线段的首尾相连、重叠或包含”,合并成一条线段。

这部分比较好处理,以方向为第一关键字,然后 \(x\) 或者 \(y\) 为第二关键字,最后 \(l\) 或者 \(d\) 为第三关键字排序。然后按顺序枚举线段,方向不同必然是新的线段,如果 \(x\) 或者 \(y\) 不同也是,否则根据 \(l,r\) 或者 \(u,d\) 判断是否“首尾相连、重叠或包含”,进行处理即可。

之后如果不是恰好 \(15\) 条线段,那么就是 No

然后数据规模缩小到了 \(15\),属于是咋做都行了。我们跑一遍洪水填充,把每个连通块标记出来,看一眼是不是恰好 \(5\) 个连通块,不是就是 No

接着判断这 \(5\) 个连通块的大小是不是 \(2,3,3,3,4\)(顺序可打乱),如果不是也是 No

继续判断就需要抓特征。可以先判断大小为 \(2\) 的连通块是不是 T,然后判断大小为 \(4\) 的连通块是不是 P。我们还观察到,剩余的连通块里只有 C 有两条横向线段。这些都可以根据题目的要求判掉。最后剩下的 UH 类似判一下,拿 bool 变量存一下就好了。

如果恰好是 THUPC,就 Yes;否则 No

赛时代码:

//By: Luogu@rui_er(122461) & registerGen(242702)
//Team: 世一大附中老同志
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
#define debug printf("Running %s on line %d...\n",__FUNCTION__,__LINE__)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const int N = 1e5+5;

int n, vis[N], sz[N];
#define No do{return puts("No")&0;}while(0)
#define Yes do{return puts("Yes")&0;}while(0)
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
struct Segment {
	int op, l, r, u, d;
	Segment(int op=0, int a=0, int b=0, int c=0, int d=0) : op(op), l(a), r(b), u(c), d(d) {}
	~Segment() {}
	friend bool operator < (const Segment& a, const Segment& b) {
		if(a.op != b.op) return a.op < b.op;
		if(!a.op) {
			if(a.u != b.u) return a.u < b.u;
			return a.l < b.l;
		}
		else {
			if(a.l != b.l) return a.l < b.l;
			return a.d < b.d;
		}
	}
}a[N], b[N];
bool intersect(Segment a, Segment b) {
	if(a.op == b.op) return 0;
	if(a.op > b.op) swap(a, b);
	if(b.l < a.l || b.l > a.r) return 0;
	if(a.u > b.u || a.u < b.d) return 0;
	return 1;
}
void dfs_floodfill(int u, int c) {
	vis[u] = c;
	++sz[c];
	rep(i, 1, 15) {
		if(i == u || vis[i]) continue;
		if(intersect(b[i], b[u])) {
			dfs_floodfill(i, c);
		}
	}
}

int main() {
	scanf("%d", &n);
	rep(i, 1, n) {
		int op, A, B, C;
		scanf("%d%d%d%d", &op, &A, &B, &C);
		if(!op) a[i] = Segment(op, A, B, C, C);
		else a[i] = Segment(op, C, C, B, A);
	}
	sort(a+1, a+1+n);
	int tot = 1;
	b[1] = a[1];
	rep(i, 2, n) {
		if(a[i].op != b[tot].op) b[++tot] = a[i];
		else if(!a[i].op) {
			if(a[i].u == b[tot].u) {
				if(b[tot].r >= a[i].l) chkmax(b[tot].r, a[i].r);
				else b[++tot] = a[i];
			}
			else b[++tot] = a[i];
		}
		else {
			if(a[i].l == b[tot].l) {
				if(b[tot].u >= a[i].d) chkmax(b[tot].u, a[i].u);
				else b[++tot] = a[i];
			}
			else b[++tot] = a[i];
		}
	}
//	rep(i, 1, tot) printf("%d %d %d %d %d\n", b[i].op, b[i].l, b[i].r, b[i].u, b[i].d);
	if(tot != 15) No;
	int totc = 0;
	rep(i, 1, 15) {
		if(!vis[i]) dfs_floodfill(i, ++totc);
	}
	if(totc != 5) No;
	int buc[5] = {0, 0, 0, 0, 0};
	rep(i, 1, 5) {
		if(sz[i] < 2 || sz[i] > 4) No;
		++buc[sz[i]];
	}
	if(buc[2] != 1 || buc[3] != 3 || buc[4] != 1) No;
	int H = 0, U = 0;
	rep(i, 1, 5) {
//		printf("COLOR %d: ", i);
		if(sz[i] == 2) { // T
			int ok = 0;
			rep(j, 1, 15) { // - 1
				if(vis[j] != i || b[j].op) continue;
				rep(k, 1, 15) { // | 2
					if(vis[k] != i || !b[k].op) continue;
					if(b[k].d < b[j].u
					 && b[j].u == b[k].u
					 && b[j].l < b[k].l
					 && b[k].l < b[j].r)
						ok = 1;
				}
			}
			if(!ok) No;
//			puts("T");
		}
		else if(sz[i] == 4) { // P
			int ok = 0;
			rep(j, 1, 15) { // | long 9
				if(vis[j] != i || !b[j].op) continue;
				rep(k, 1, 15) { // | short 12
					if(vis[k] != i || !b[k].op) continue;
					if(j == k || b[j].u - b[j].d <= b[k].u - b[k].d) continue;
					rep(l, 1, 15) { // - up 10
						if(vis[l] != i || b[l].op) continue;
						rep(m, 1, 15) { // - down 11
							if(l == m || vis[m] != i || b[m].op) continue;
							if(b[j].d < b[m].d
							 && b[m].d == b[k].d
							 && b[k].d < b[j].u
							 && b[j].u == b[l].u
							 && b[l].u == b[k].u
							 && b[j].l == b[l].l
							 && b[l].l == b[m].l
							 && b[m].l < b[l].r
							 && b[l].r == b[m].r
							 && b[m].r == b[k].l)
								ok = 1;
						}
					}
				}
			}
			if(!ok) No;
//			puts("P");
		}
		else { // H | U | C
			int _ = 0; // -
			rep(j, 1, 15) {
				if(!b[j].op && vis[j] == i) {
					++_;
				}
			}
			if(_ == 2) { // C
				int ok = 0;
				rep(j, 1, 15) { // | 13
					if(vis[j] != i || !b[j].op) continue;
					rep(k, 1, 15) { // - up 14
						if(vis[k] != i || b[k].op) continue;
						rep(l, 1, 15) { // - down 15
							if(k == l || vis[l] != i || b[l].op) continue;
							if(b[l].d >= b[k].d) continue;
							if(b[j].d == b[l].d
							 && b[l].d < b[j].u
							 && b[j].u == b[k].d
							 && b[j].l == b[k].l
							 && b[k].l == b[l].l
							 && b[l].l < b[k].r
							 && b[k].r == b[l].r)
								ok = 1;
						}
					}
				}
				if(!ok) No;
//				puts("C");
			}
			else {
				// H
				int okH = 0;
				rep(j, 1, 15) { // | left 3
					if(vis[j] != i || !b[j].op) continue;
					rep(k, 1, 15) { // - 4
						if(vis[k] != i || b[k].op) continue;
						rep(l, 1, 15) { // | right 5
							if(j == l || vis[l] != i || !b[l].op) continue;
							if(b[l].l <= b[j].l) continue;
							if(b[j].d == b[l].d
							 && b[l].d < b[k].d
							 && b[k].d < b[j].u
							 && b[j].u == b[l].u
							 && b[j].l == b[k].l
							 && b[k].l < b[k].r
							 && b[k].r == b[l].l)
								okH = 1;
						}
					}
				}
				// U
				int okU = 0;
				rep(j, 1, 15) { // | left 6
					if(vis[j] != i || !b[j].op) continue;
					rep(k, 1, 15) { // - 7
						if(vis[k] != i || b[k].op) continue;
						rep(l, 1, 15) { // | right 8
							if(j == l || vis[l] != i || !b[l].op) continue;
							if(b[l].l <= b[j].l) continue;
							if(b[j].d == b[l].d
							 && b[l].d == b[k].d
							 && b[k].d < b[j].u
							 && b[j].u == b[l].u
							 && b[j].l == b[k].l
							 && b[k].l < b[k].r
							 && b[k].r == b[l].l)
								okU = 1;
						}
					}
				}
				H |= okH;
				U |= okU;
//				if(okH) puts("H");
//				if(okU) puts("U");
			}
		}
	}
	if(H && U) Yes;
	else No;
	return 0;
}
posted @ 2022-03-22 21:01  rui_er  阅读(90)  评论(0编辑  收藏  举报