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

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

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

首先,一开始有 105 条线段,而 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 @   rui_er  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示