題解洛谷 P8216【[THUPC2022 初賽] 畫圖】
阿新 • • 發佈:2022-03-22
大模擬,應該還算大模擬裡面偏簡單的。
正如官方題解說的,本題難點在於注意到這道題是可做題。
首先,一開始有 \(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
有兩條橫向線段。這些都可以根據題目的要求判掉。最後剩下的 U
和 H
類似判一下,拿 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; }