题解:AT_arc226_c [ARC226C] Square Corner Packing
有意思题。激战一个小时做出来了。
尝试分析操作次数的上界,不妨转化成剩余白色格子数量
显然要有
观察到每次操作,每行减少的白色格子数量为
容易发现
下面考虑
不妨先考虑
先把四个角涂黑,再风车状地做
这样恰好留下来了
进一步地,我们发现这个构造可以递归。具体来说,对于
例如,对于
不难证明这样的递归构造恰好会留下
对于
现在回到原来的问题,不妨设
时间复杂度
:::success[代码]
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int MAXN = 505;
template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
constexpr int lg2(ll x) { return 63 ^ __builtin_clzll(x); }
constexpr ll bitCeil(ll x) { return x == 1 ? 1ll : 1ll << lg2(x - 1) + 1; }
int tc, n, m;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> tc;
while (tc--) {
cin >> n >> m;
if ((~n & 1) || (~m & 1)) {
int x = 0;
if ((~n & 1) && (m & 1)) x = n;
else if ((~m & 1) && (n & 1)) x = m;
cout << (n * m - x >> 2) << '\n';
for (int i = 1; i < n; i += 2) {
for (int j = 1; j < m; j += 2) {
cout << i << ' ' << j << ' ' << 1 << '\n';
}
}
} else {
auto [mn, mx] = minmax({n, m});
cout << (n * m - mx >> 2) << '\n';
auto square1 = [&](auto &&self, int n, int x, int y) -> void {
if (n == 1) return;
cout << x << ' ' << y << ' ' << n - 1 << '\n';
for (int i = 1; i < n - 2; i += 2) cout << x << ' ' << y + i << ' ' << 1 << '\n';
for (int i = 1; i < n - 2; i += 2) cout << x + i << ' ' << y + n - 2 << ' ' << 1 << '\n';
for (int i = n - 3; i > 1; i -= 2) cout << x + n - 2 << ' ' << y + i << ' ' << 1 << '\n';
for (int i = n - 3; i > 1; i -= 2) cout << x + i << ' ' << y << ' ' << 1 << '\n';
self(self, n - 4, x + 2, y + 2);
};
auto square3 = [&](int n, int x, int y) {
square1(square1, n - 2, x, y);
for (int i = 1; i < n; i += 2) cout << i << ' ' << n - 1 << ' ' << 1 << '\n';
for (int i = 1; i < n - 2; i += 2) cout << n - 1 << ' ' << i << ' ' << 1 << '\n';
};
if (mn % 4 == 1) square1(square1, mn, 1, 1);
else square3(mn, 1, 1);
if (n < m) {
for (int i = 1; i < n; i += 2) {
for (int j = n + 1; j < m; j += 2) {
cout << i << ' ' << j << ' ' << 1 << '\n';
}
}
} else {
for (int i = m + 1; i < n; i += 2) {
for (int j = 1; j < m; j += 2) {
cout << i << ' ' << j << ' ' << 1 << '\n';
}
}
}
}
}
return 0;
}
:::