競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 312E

ABC312E

何を全探索するかを考えるのが基本. 座標の範囲 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;
    }
  }

  vector<set<ll>> ans(n+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;
}