NC221008. 拱桥(Hard Version)
描述
本题有Easy,Hard两个版本,两个版本之间的区别仅在数据范围,通过Hard Version的代码可以直接通过Easy Version。保证Easy Version的测试用例集是Hard Version的子集
输入描述
首先输入一个正整数
表示有T组测试案例,对于每组测试案例:
第一行输入两个正整数表示棋盘的大小是n行m列。
第二行输入一个坐标输入数据保证
输出描述
对于每组测试案例:
输出n行,每行m个数字。每个坐标上的数字表示桥墩属于哪一座桥,一座桥有两个桥墩。
你可以用俩个相同的正整数表示一座桥,注意同一座桥的两个桥墩之间的欧几里得距离应该在之间。
如果某个格子上没有桥墩,则在该位置输出“-1”。
请保证坐标上的数字为“-1”。
示例1
输入:
1 3 3 2 2
输出:
1 2 3 3 -1 1 4 2 4
说明:
构造方案如题面上的图片所示。C++ 解法, 执行用时: 240ms, 内存消耗: 97112K, 提交时间: 2021-10-15 21:58:10
#include<bits/stdc++.h> #define L(i, j, k) for (int i = (j); i <= (k); ++i) #define R(i, j, k) for (int i = (j); i >= (k); --i) #define ll long long #define vi vector < int > #define sz(a) ((int) (a).size()) using namespace std; const int N = 1e6 + 7; int n, m, nowc, px, py, mat[N], tp, a[N], vis[N], rtp; vi e[N]; mt19937 orz(time(0) ^ clock()); bool dfs (int x) { vis[x] = rtp; for (const int &v : e[x]) { int f = mat[v]; if (vis[f] == rtp) continue; mat[x] = v, mat[v] = x, mat[f] = false; if (!f || dfs (f)) return true; mat[v] = f, mat[f] = v, mat[x] = false; } return 0; } bool iP (int x, int y) { return x == px && y == py; } vi id[N]; int top; void Main () { // n = 4, m = 100, px = 1, py = 1; cin >> n >> m >> px >> py; L(i, 0, n * m) a[i] = -1, mat[i] = 0; L(i, 1, n) id[i].resize(m + 1); top = 0; int rt = 0, ln = 1, rn = n, lm = 1, rm = m; while (px - ln >= 10) { L(i, ln, ln + 1) L(j, lm, rm) ++top, e[top].clear(), id[i][j] = id[i + 2][j] = top, a[top] = ++rt; ln += 4; } while (rn - px >= 10) { rn -= 4; L(i, rn + 1, rn + 2) L(j, lm, rm) ++top, e[top].clear(), id[i][j] = id[i + 2][j] = top, a[top] = ++rt; } while (py - lm >= 10) { L(i, ln, rn) L(j, lm, lm + 1) ++top, e[top].clear(), id[i][j] = id[i][j + 2] = top, a[top] = ++rt; lm += 4; } while (rm - py >= 10) { rm -= 4; L(i, ln, rn) L(j, rm + 1, rm + 2) ++top, e[top].clear(), id[i][j] = id[i][j + 2] = top, a[top] = ++rt; } L(i, 1, n) L(j, 1, m) if((ln <= i && i <= rn) && (lm <= j && j <= rm) && !iP(i, j)) id[i][j] = ++top, e[top].clear (); id[px][py] = 0; L(i, 1, n) L(j, 1, m) if((ln <= i && i <= rn) && (lm <= j && j <= rm) && !iP(i, j)) L(wi, max(i - 2, 1), min(i + 2, n)) L(wj, max(j - 2, 1), min(j + 2, m)) if((ln <= wi && wi <= rn) && (lm <= wj && wj <= rm) && !iP(wi, wj)) { int cnt = (abs(wi - i) == 2) + (abs(wj - j) == 2) ; if(cnt == 1) e[id[i][j]].push_back(id[wi][wj]); } vi cur (top); L(i, 0, top - 1) cur[i] = i + 1; shuffle(cur.begin(), cur.end(), orz); for (const int &x : cur) if (!mat[x]) ++rtp, dfs (x); L(i, 1, top) if(i < mat[i]) a[i] = a[mat[i]] = ++rt; L(i, 1, n) L(j, 1, m) cout << a[id[i][j]] << " \n"[j == m]; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int T = 1; cin >> T; while (T--) Main (); return 0; }