1. 程式人生 > 其它 >題解洛谷 P8216【[THUPC2022 初賽] 畫圖】

題解洛谷 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;
}