随记 – THUPC 2022 初赛 J – 画图 7KB的大模拟……?

作者:

在

考虑合并若干重叠线段。使其有序化后考虑每两个线段的交,如果其为空则新建一条独立线段,反之合并。

最后应当恰好有$7$条水平线段,$8$条垂直线段,否则依题意不可能拼凑出“$\textbf{THUPC}$”图形。

DFS搜索组成每个字母的所有可能线段组合。需要合理剪枝,亦可以使用二进制状态压缩减小常数。时间复杂度理论上限为$\mathrm{O}(7^5\times 8^5)$,实际远远达不到。

赛时1A(实际上因为无主函数返回值RE了两次)$7\text{KB}$代码:

#include <bits/stdc++.h>
using namespace std;

template <typename T> inline bool read (T &x) {
	x = 0; int f = 1; char c = getchar ();
	for (; c != EOF && !isdigit (c); c = getchar ())
		if (c == '-') f = -1;
	if (c == EOF) return 0;
	for (; c != EOF && isdigit (c); c = getchar ())
		x = (x<<1) + (x<<3) + (c^48);
	x *= f; return 1;
}
template <typename T, typename... Targs>
inline bool read (T &x, Targs&... args) {
	return read (x) && read (args...); }
template <typename T> void print (T x) {
	if (x < 0) putchar ('-'), x = -x;
	if (x > 9) print (x / 10);
	putchar ('0' + x % 10);
}
template <typename T, typename... Targs>
inline void print (T x, Targs... args) {
	print (x), putchar (' '), print (args...); }
#define reint register int
#define inl inline
#define newl putchar('\n')
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 lll;
// typedef long double llf;
typedef pair <int, int> pint;

constexpr int N = 1e5 + 10, INF = 0x3f3f3f3f;
int n, opt, l, r, y, u, v, x;
int gcnt, pcnt, gscnt, pscnt; bool flag;
struct segment {
	int st, ed, con;
	bool operator < (const segment& b) const {
		return con != b.con ? con < b.con :
			(st != b.st ? st < b.st : ed < b.ed);
	}
} g[N], p[N], gseg[N], pseg[N];

inl bool upd_seg (segment &_g, segment &_t) {
	if (_g.con != _t.con) return 0;
	if (_t.st >= _g.st && _t.st <= _g.ed) {
		_g.ed = max (_g.ed, _t.ed);
		return 1;
	} else if (_t.ed >= _g.st && _t.ed <= _g.ed) {
		_g.st = min (_g.st, _t.st);
		return 1;
	}
	return 0;
}

#define lowbit(x) (x & -x)
int glst[5][10], glcnt[5], saigo[18],
	plst[5][10], plcnt[5], log2s[1<<9];
inl void _tenkai (int msk, int lst[], int &lcnt) {
	lcnt = 0; int tmp;
	while (msk)
		tmp = lowbit(msk),
		lst[++lcnt] = log2s[tmp],
		msk -= tmp;
}
#define tenkai(i) (_tenkai (gmsk, glst[i], glcnt[i]),\
	_tenkai (pmsk, plst[i], plcnt[i]))

inl bool diff (int x, int y) {
	if (x <= 2) return y > 2;
	else if (x <= 5)
		return !(y > 2 && y <= 5);
	else if (x <= 8)
		return !(y > 5 && y <= 8);
	else if (x <= 12)
		return !(y > 8 && y <= 12);
	else return y <= 12;
}
inl bool dir (int x) {
	switch (x) {
		case 1: case 4: case 7:
		case 10: case 11: case 14: case 15:
		return 1;
		default: return 0;
	}
}
inl bool inter (int i, int j) {
	int o, q;
	o = saigo[i], q = saigo[j];
	if (!dir (i)) swap (o, q);
	if (gseg[o].ed < pseg[q].con) return 0;
	if (gseg[o].st > pseg[q].con) return 0;
	if (gseg[o].con > pseg[q].ed) return 0;
	if (gseg[o].con < pseg[q].st) return 0;
	return 1;
}
inl void check () {
	for (int i = 1; i <= 15; ++i)
		for (int j = i + 1; j <= 15; ++j) {
			if (!diff (i, j)) continue;
			if (dir (i) == dir (j)) continue;
			if (inter (i, j)) return;
		}
	flag = 1;
}
inl void C (int gmsk, int pmsk) {
	if (flag) return;
	tenkai (4); // remain: 2, 1
	segment *o = &pseg[plst[4][1]], *q, *r;
	saigo[13] = plst[4][1];
	for (int j = 1; j <= 2; ++j) {
		int k = 3 - j;
		q = &gseg[glst[4][j]],
		r = &gseg[glst[4][k]];
		if (!(o->con == q->st && q->st == r->st   
			&& q->ed == r->ed && o->ed == q->con  
			&& o->st == r->con)) continue;
		saigo[14] = glst[4][j],
		saigo[15] = glst[4][k];
		check ();
	}
}
inl void P (int gmsk, int pmsk) {
	if (flag) return;
	tenkai (3); // remain: 4, 3
	segment *o, *q, *r, *t;
	int *_plst = plst[3], *_glst = glst[3];
	for (int i = 1; i <= 3; ++i) {
		o = &pseg[_plst[i]];
		for (int l = 1; l <= 3; ++l) {
			if (l == i) continue;
			t = &pseg[_plst[l]];
			for (int j = 1; j <= 4; ++j) {
				q = &gseg[_glst[j]];
				for (int k = 1; k <= 4; ++k) {
					if (j == k) continue;
					r = &gseg[_glst[k]];
					if (!(o->st < r->con && r->con < o->ed
						&& o->ed == q->con && o->con == r->st && r->st == q->st
						&& q->ed == r->ed && q->con == t->ed
						&& t->st == r->con && t->con == q->ed)) continue;
					saigo[9] = _plst[i],
					saigo[10] = _glst[j],
					saigo[11] = _glst[k],
					saigo[12] = _plst[l];
					C (gmsk ^ (1<<_glst[j] - 1) ^ (1<<_glst[k] - 1),
						pmsk ^ (1<<_plst[i] - 1) ^ (1<<_plst[l] - 1));
				}
			}
		}
	}
}
inl void U (int gmsk, int pmsk) {
	if (flag) return;
	tenkai (2); // remain: 5, 5
	segment *o, *q, *r;
	int *_plst = plst[2], *_glst = glst[2];
	for (int i = 1; i <= 5; ++i) {
		o = &pseg[_plst[i]];
		for (int k = 1; k <= 5; ++k) {
			if (i == k) continue;
			r = &pseg[_plst[k]];
			for (int j = 1; j <= 5; ++j) {
				q = &gseg[_glst[j]];
				if (!(o->st == r->st && o->ed == r->ed
					&& q->con == o->st && q->st == o->con
					&& q->ed == r->con)) continue;
				saigo[6] = _plst[i],
				saigo[7] = _glst[j],
				saigo[8] = _plst[k];
				P (gmsk ^ (1<<_glst[j] - 1),
					pmsk ^ (1<<_plst[i] - 1) ^ (1<<_plst[k] - 1));
			}
		}
	}
}
inl void H (int gmsk, int pmsk) {
	if (flag) return;
	tenkai (1); // remain: 6, 7
	segment *o, *q, *r;
	int *_plst = plst[1], *_glst = glst[1];
	for (int i = 1; i <= 7; ++i) {
		o = &pseg[_plst[i]];
		for (int k = 1; k <= 7; ++k) {
			if (k == i) continue;
			r = &pseg[_plst[k]];
			for (int j = 1; j <= 6; ++j) {
				q = &gseg[_glst[j]];
				if (!(o->st == r->st && o->ed == r->ed
					&& q->con > o->st && q->con < o->ed
					&& q->st == o->con && q->ed == r->con)) continue;
				saigo[3] = _plst[i],
				saigo[4] = _glst[j],
				saigo[5] = _plst[k];
				U (gmsk ^ (1<<_glst[j] - 1),
					pmsk ^ (1<<_plst[i] - 1) ^ (1<<_plst[k] - 1));
			}
		}
	}
}
inl void T (int gmsk, int pmsk) {
	if (flag) return;
	tenkai (0); // remain: 7, 8
	int o, q;
	for (int i = 1; i <= 7; ++i)
		for (int j = 1; j <= 8; ++j) {
			o = glst[0][i], q = plst[0][j];
			if (!((gseg[o].con == pseg[q].ed) && (gseg[o].ed > pseg[q].con
				&& gseg[o].st < pseg[q].con))) continue;
			saigo[1] = o,
			saigo[2] = q;
			H (gmsk ^ (1<<o - 1), pmsk ^ (1<<q - 1));
		}
}

int main () {
	/* THUPC 2022 初赛 J - 画图 thupc341 */
	read (n);
	for (int i = 1; i <= n; ++i) {
		read (opt);
		if (opt == 0) {
			read (l, r, y);
			g[++gcnt] = { l, r, y };
		} else {
			read (u, v, x);
			p[++pcnt] = { u, v, x };
		}
	}
	sort (g + 1, g + gcnt + 1);
	sort (p + 1, p + pcnt + 1);
	gseg[0].con = pseg[0].con = -INF;
	for (int i = 1; i <= gcnt; ++i)
		if (upd_seg (gseg[gscnt], g[i]));
		else gseg[++gscnt] = g[i];
	for (int i = 1; i <= pcnt; ++i)
		if (upd_seg (pseg[pscnt], p[i]));
		else pseg[++pscnt] = p[i];
	if (gscnt != 7 || pscnt != 8)
		return puts ("No"), 0;

	for (int i = 0; i < 8; ++i)
		log2s[1<<i] = i + 1;
	T (0b1111111, 0b11111111);
	puts (flag ? "Yes" : "No");

	return 0;
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注