何を全探索するかを考えるのが基本. 座標の範囲 100 と小さいので,3次元で全探索しても \(O(100^{3})\) で間に合う. よって,それを軸に考える.
座標で全探索するということは,境目になる面を全探索しているのと同じ. しかし,面を全探索するのは実装が大変. そこで,内側の小立方体を全探索する方針にする.
\(M := 100\) とする. 問題の仮定から,各小立方体 \(c \in M^3\) に対して,どの直方体に属するかは一意に決まるので, それを \(f(c) \in N \cup \{*\}\) とおく. ここで \(*\) は,どの直方体にも属してないことを表す. \(c\) に隣接する小立方体 \(d \in M^3\) に対して,
- \(f(c) \neq f(d)\) かつ
- \(c \neq * \neq d\)
が,\(c\) が満たすべき必要十分条件.
実装:
\(c \in M^{3}\) を全探索して, \(c\) に隣接する \(d \in M^{3}\) に対して, 条件を満たすか判定する. 満たしている場合は set の vector \(a\) を用いて, \(a[c].insert(d);\) \(a[d].insert(c);\) の様にする.
使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"
const ll m = 100;
ll a[m+2][m+2][m+2];
int main() {
ll n;
cin >> n;
rep(i,n){
ll x,y,z;
ll nx,ny,nz;
cin >> x >> y >> z >> nx >> ny >> nz;
srep(s,x,nx) srep(t,y,ny) srep(u,z,nz){
a[s][t][u] = i+1;
}
}
auto add = [&](ll i, ll j) -> void {
ans[i].insert(j);
ans[j].insert(i);
};
rep(x,m+1) rep(y,m+1) rep(z,m+1){
ll now = a[x][y][z];
if(now && a[x+1][y][z] && a[x+1][y][z]!=now) add(now, a[x+1][y][z]);
if(now && a[x][y+1][z] && a[x][y+1][z]!=now) add(now, a[x][y+1][z]);
if(now && a[x][y][z+1] && a[x][y][z+1]!=now) add(now, a[x][y][z+1]);
}
rep1(i,n) cout << ans[i].size() << endl;
return 0;
}