takapt0226's diary

競技プログラミングのことを書きます

AOJ 580 Fish (おそらく非想定解?)

AOJで他の解法投げると見れなくなると思うので,とりあえずコード貼っておきます

解法

直方体とその領域で重なっている数を持っておく.

ソースコード

struct Rect
{
    int v[3][2];
    ll calc_area() const
    {
        ll res = 1;
        rep(d, 3)
            res *= v[d][1] - v[d][0];
        return res;
    }
};
typedef pair<Rect, int> Area; // (rect, num of fishes)

bool intersect(const Rect& a, const Rect& b, Rect& r)
{
    rep(d, 3)
    {
        r.v[d][0] = max(a.v[d][0], b.v[d][0]);
        r.v[d][1] = min(a.v[d][1], b.v[d][1]);
        if (r.v[d][0] >= r.v[d][1])
            return false;
    }
    return true;
}

int main()
{
    int n, k;
    cin >> n >> k;

    const int inf = ten(8);
    Rect inf_rect;
    rep(d, 3)
    {
        inf_rect.v[d][0] = -inf;
        inf_rect.v[d][1] = inf;
    }

    vector<Area> area;
    area.pb(make_pair(inf_rect, 0));
    rep(fi, n)
    {
        Rect fish;
        rep(i, 2) rep(d, 3)
            cin >> fish.v[d][i];

        vector<Area> narea;
        foreach (it, area)
        {
            Rect and_rect;
            if (intersect(fish, it->first, and_rect))
            {
                narea.pb(make_pair(and_rect, it->second + 1));

                int bound[3][4];
                rep(d, 3)
                {
                    bound[d][0] = -inf;
                    bound[d][1] = and_rect.v[d][0];
                    bound[d][2] = and_rect.v[d][1];
                    bound[d][3] = inf;
                }

                rep(i, 3) rep(j, 3) rep(k, 3)
                {
                    if (i == 1 && j == 1 && k == 1)
                    {
                        // excluding: temp_rect == and_rect
                        continue;
                    }

                    Rect temp_rect;
                    temp_rect.v[0][0] = bound[0][i];
                    temp_rect.v[0][1] = bound[0][i + 1];

                    temp_rect.v[1][0] = bound[1][j];
                    temp_rect.v[1][1] = bound[1][j + 1];

                    temp_rect.v[2][0] = bound[2][k];
                    temp_rect.v[2][1] = bound[2][k + 1];

                    Rect and_r;
                    if (intersect(temp_rect, it->first, and_r))
                        narea.pb(make_pair(and_r, it->second));
                }
            }
            else
                narea.pb(*it);
        }

        area = narea;
    }

    ll res = 0;
    foreach (it, area)
        if (it->second >= k)
            res += it->first.calc_area();
    cout << res << endl;
}