QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#162363#7105. Pixel Artucup-team133AC ✓612ms28612kbC++239.2kb2023-09-03 11:15:142023-09-04 04:31:20

Judging History

你现在查看的是最新测评结果

  • [2023-09-04 04:31:20]
  • 自动重测本题所有获得100分的提交记录
  • 测评结果:AC
  • 用时:612ms
  • 内存:28612kb
  • [2023-09-03 11:15:14]
  • 评测
  • 测评结果:100
  • 用时:648ms
  • 内存:28420kb
  • [2023-09-03 11:15:14]
  • 提交

answer

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...) void(0)
#endif

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

}  // namespace atcoder

using namespace std;

typedef long long ll;
#define all(x) begin(x), end(x)
constexpr int INF = (1 << 30) - 1;
constexpr long long IINF = (1LL << 60) - 1;
constexpr int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};

template <class T> istream& operator>>(istream& is, vector<T>& v) {
    for (auto& x : v) is >> x;
    return is;
}

template <class T> ostream& operator<<(ostream& os, const vector<T>& v) {
    auto sep = "";
    for (const auto& x : v) os << exchange(sep, " ") << x;
    return os;
}

template <class T, class U = T> bool chmin(T& x, U&& y) { return y < x and (x = forward<U>(y), true); }

template <class T, class U = T> bool chmax(T& x, U&& y) { return x < y and (x = forward<U>(y), true); }

template <class T> void mkuni(vector<T>& v) {
    sort(begin(v), end(v));
    v.erase(unique(begin(v), end(v)), end(v));
}

template <class T> int lwb(const vector<T>& v, const T& x) { return lower_bound(begin(v), end(v), x) - begin(v); }

void solve() {
    int n, m, K;
    cin >> n >> m >> K;
    vector<int> lx(K), ly(K), rx(K), ry(K);
    vector<vector<int>> row(n);
    map<int, vector<int>> col;
    for (int i = 0; i < K; i++) {
        cin >> lx[i] >> ly[i] >> rx[i] >> ry[i];
        lx[i]--, ly[i]--;
        if (rx[i] - lx[i] == 1)
            row[lx[i]].emplace_back(i);
        else {
            assert(ry[i] - ly[i] == 1);
            col[ly[i]].emplace_back(i);
        }
    }

    vector<vector<int>> revivers(n);
    vector<vector<pair<int, int>>> es(n);
    vector<int> rowsum(n, 0), colsum(n + 1, 0);
    for (int i = 0; i < K; i++) {
        revivers[lx[i]].emplace_back(i);
        if (rx[i] - lx[i] == 1)
            rowsum[lx[i]] += ry[i] - ly[i];
        else {
            colsum[lx[i]]++;
            colsum[rx[i]]--;
        }
    }
    for (int i = 0; i < n; i++) colsum[i + 1] += colsum[i];
    {
        // 横と横が横に隣接
        for (int i = 0; i < n; i++) {
            sort(begin(row[i]), end(row[i]), [&](int l, int r) { return ly[l] < ly[r]; });
            for (int j = 0; j + 1 < int(row[i].size()); j++) {
                int l = row[i][j], r = row[i][j + 1];
                if (ry[l] == ly[r]) es[i].emplace_back(l, r);
            }
        }
    }
    {
        // 横と横が縦に隣接
        for (int i = 0; i + 1 < n; i++) {
            vector<tuple<int, int, int>> events;
            for (int& idx : row[i]) {
                events.emplace_back(ly[idx], idx, 0);
                events.emplace_back(ry[idx], -1, 0);
            }
            for (int& idx : row[i + 1]) {
                events.emplace_back(ly[idx], idx, 1);
                events.emplace_back(ry[idx], -1, 1);
            }
            sort(begin(events), end(events));
            vector<int> cur(2, -1);
            for (auto [tmp, idx, pos] : events) {
                if (idx == -1)
                    cur[pos] = -1;
                else {
                    cur[pos] = idx;
                    if (cur[0] >= 0 and cur[1] >= 0) es[i + 1].emplace_back(cur[0], cur[1]);
                }
            }
        }
    }
    {
        // 縦と縦が縦に隣接
        for (auto& [y, v] : col) {
            sort(begin(v), end(v), [&](int l, int r) { return lx[l] < lx[r]; });
            for (int j = 0; j + 1 < int(v.size()); j++) {
                int l = v[j], r = v[j + 1];
                if (rx[l] == lx[r]) es[lx[r]].emplace_back(l, r);
            }
        }
    }
    {
        // 縦と縦が横に隣接
        for (auto& [y, v] : col) {
            if (not col.count(y + 1)) continue;
            auto& u = col[y + 1];
            vector<tuple<int, int, int>> events;
            for (int& idx : v) {
                events.emplace_back(lx[idx], idx, 0);
                events.emplace_back(rx[idx], -1, 0);
            }
            for (int& idx : u) {
                events.emplace_back(lx[idx], idx, 1);
                events.emplace_back(rx[idx], -1, 1);
            }
            sort(begin(events), end(events));
            vector<int> cur(2, -1);
            for (auto [tmp, idx, pos] : events) {
                if (idx == -1)
                    cur[pos] = -1;
                else {
                    cur[pos] = idx;
                    if (cur[0] >= 0 and cur[1] >= 0) es[tmp].emplace_back(cur[0], cur[1]);
                }
            }
        }
    }
    {
        // 横と縦が横に隣接
        map<int, int> cur;
        vector<vector<pair<int, int>>> events(n + 1);
        for (auto& [y, v] : col) {
            for (int& idx : v) {
                events[lx[idx]].emplace_back(idx, y);
                events[rx[idx]].emplace_back(-1, y);
            }
        }
        for (int i = 0; i < n; i++) {
            sort(begin(events[i]), end(events[i]));
            for (auto [idx, pos] : events[i]) cur[pos] = idx;
            for (int& idx : row[i]) {
                {
                    int val = ly[idx] - 1;
                    if (val >= 0 and cur.count(val) and cur[val] >= 0) es[i].emplace_back(idx, cur[val]);
                }
                {
                    int val = ry[idx];
                    if (val < m and cur.count(val) and cur[val] >= 0) es[i].emplace_back(idx, cur[ry[idx]]);
                }
            }
        }
    }
    {
        // 横と縦が縦に隣接
        vector<int> cur(n, -1);
        map<int, vector<pair<int, int>>> events;
        for (int i = 0; i < n; i++) {
            for (int& idx : row[i]) {
                events[ly[idx]].emplace_back(idx, i);
                events[ry[idx]].emplace_back(-1, i);
            }
        }
        for (auto& [y, v] : col) events[y].emplace_back(-2, -2);
        for (auto& [i, v] : events) {
            sort(begin(v), end(v));
            for (auto [idx, pos] : v) {
                if (pos == -2) continue;
                cur[pos] = idx;
            }
            for (int& idx : col[i]) {
                if (lx[idx] - 1 >= 0 and cur[lx[idx] - 1] >= 0) es[lx[idx]].emplace_back(idx, cur[lx[idx] - 1]);
                if (rx[idx] < n and cur[rx[idx]] >= 0) es[rx[idx]].emplace_back(idx, cur[rx[idx]]);
            }
        }
    }
    atcoder::dsu dsu(K);
    int ans = 0;
    ll black = 0;
    vector<int> cnt(K, 0);
    auto REVIVE = [&](int v) {
        v = dsu.leader(v);
        ans -= (cnt[v] > 0);
        cnt[v]++;
        ans += (cnt[v] > 0);
    };
    auto MERGE = [&](int u, int v) {
        u = dsu.leader(u), v = dsu.leader(v);
        if (u == v) return;
        ans -= (cnt[u] > 0);
        ans -= (cnt[v] > 0);
        int w = dsu.merge(u, v);
        cnt[w] = cnt[u] + cnt[v];
        ans += (cnt[w] > 0);
    };
    for (int i = 0; i < n; i++) {
        black += rowsum[i];
        black += colsum[i];
        for (int& v : revivers[i]) REVIVE(v);
        for (auto [u, v] : es[i]) MERGE(u, v);
        cout << black << ' ' << ans << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin >> T;
    for (; T--;) solve();
    return 0;
}

这程序好像有点Bug,我给组数据试试?

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 2ms
memory: 3608kb

input:

3
2 5 2
1 1 1 2
2 3 2 5
2 5 2
1 1 1 3
2 3 2 5
3 3 3
1 1 1 2
3 1 3 2
1 3 2 3

output:

2 1
5 2
3 1
6 1
3 1
4 1
6 2

result:

ok 7 lines

Test #2:

score: 0
Accepted
time: 612ms
memory: 28612kb

input:

2130
2 5 2
1 1 1 2
2 3 2 5
2 5 2
1 1 1 3
2 3 2 5
3 3 3
1 1 1 2
3 1 3 2
1 3 2 3
3 100 51
1 2 2 2
1 4 2 4
1 6 2 6
1 8 2 8
1 10 2 10
1 12 2 12
1 14 2 14
1 16 2 16
1 18 2 18
1 20 2 20
1 22 2 22
1 24 2 24
1 26 2 26
1 28 2 28
1 30 2 30
1 32 2 32
1 34 2 34
1 36 2 36
1 38 2 38
1 40 2 40
1 42 2 42
1 44 2 44
...

output:

2 1
5 2
3 1
6 1
3 1
4 1
6 2
50 50
100 50
200 1
50 50
150 1
200 1
2 1
4 1
6 1
8 1
10 1
12 1
14 1
16 1
18 1
20 1
22 1
24 1
26 1
28 1
30 1
32 1
34 1
36 1
38 1
40 1
42 1
44 1
46 1
48 1
50 1
52 1
54 1
56 1
58 1
60 1
62 1
64 1
66 1
68 1
70 1
72 1
74 1
76 1
78 1
80 1
82 1
84 1
86 1
88 1
90 1
92 1
94 1
96 1...

result:

ok 355756 lines

Extra Test:

score: 0
Extra Test Passed