Submission #577006

# Submission time Handle Problem Language Result Execution time Memory
577006 2022-06-13T21:43:21 Z PurpleCrayon Paint (COI20_paint) C++17
100 / 100
1061 ms 173532 KB
#include <bits/stdc++.h>
using namespace std;
 
#define sz(v) int(v.size())
#define ar array
typedef long long ll;
const int N = 2e5+10, MOD = 998244353;
const int B = 2e3;
 
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
 
int n, m, p[N], sz[N];
int col[N];
 
unordered_map<int, unordered_set<int>> adj_col[N];
 
int find_set(int v) {
    return v == p[v] ? v : p[v] = find_set(p[v]);
}
unordered_set<int> all_big;
void union_sets(int a, int b) { // merge, but only in the dsu
    a = find_set(a), b = find_set(b);
    if (a == b) return;
    if (sz[a] < sz[b]) swap(a, b);
    p[b] = a, sz[a] += sz[b], sz[b] = 0;
    all_big.erase(b);
}
void union_big(int a, int b) { // just merge adj_col
    a = find_set(a), b = find_set(b);
    if (a == b) return;
    if (sz[a] < sz[b]) swap(a, b);
    for (auto& [k, v] : adj_col[b]) {
        for (auto& x : v) adj_col[a][k].insert(x);
    }
    adj_col[b].clear();
}
int get_col(int v) {
    return col[find_set(v)];
}
 
int tt = 0;
int vis[N], use[N];
 
int que[N], ptr = 0;
vector<int> small_adj;
void dfs_small(int _v) {
    ptr = 0;
    que[ptr++] = _v;
    vis[_v] = tt;
 
    for (int rep = 0; rep < ptr; rep++) {
        int v = que[rep];
        int i = v / m, j = v % m;
        for (int k = 0; k < 4; k++) {
            int ni = i + dx[k], nj = j + dy[k];
            if (ni < 0 || ni >= n || nj < 0 || nj >= m) continue;
            if (vis[ni*m + nj] == tt) continue;
            if (find_set(ni*m + nj) != find_set(v)) {
                if (use[find_set(ni*m + nj)] != tt) {
                    small_adj.push_back(find_set(ni*m + nj));
                    use[find_set(ni*m + nj)] = tt;
                }
            } else {
                que[ptr++] = ni*m + nj;
                vis[ni*m + nj] = tt;
            }
        }
    }
}
void make_big(int v, bool finished_dfs = false) { // make information for v to be a big component
    if (!finished_dfs) {
        tt++;
        small_adj.clear();
        dfs_small(v);
    }
    all_big.insert(find_set(v));
    for (auto nxt : small_adj) {
        adj_col[find_set(v)][get_col(nxt)].insert(find_set(nxt));
    }
}
void add_small(int v) { // add v to the info of all surrounding big components
    tt++;
    small_adj.clear();
    dfs_small(v);
 
    for (auto nxt : small_adj) {
        if (sz[find_set(nxt)] >= B) {
            adj_col[find_set(nxt)][get_col(v)].insert(find_set(v));
        }
    }
}
void clear_comp(int v) { // remove v from the info of all surrounding big components
    for (auto nxt : all_big) {
        adj_col[nxt][get_col(v)].erase(find_set(v));
    }
}
void upd_big(int v, int x) {
    v = find_set(v);
    auto to_merge = adj_col[v][x];
    for (auto nxt : to_merge) {
        clear_comp(nxt);
    }
    clear_comp(v);
    for (auto nxt : to_merge) {
        if (sz[find_set(nxt)] < B) {
            make_big(nxt);
        }
        union_big(v, nxt);
        union_sets(v, nxt);
    }
    col[find_set(v)] = x;
    v = find_set(v);
    for (auto nxt : all_big) if (adj_col[v][get_col(nxt)].find(nxt) != adj_col[v][get_col(nxt)].end()) {
        adj_col[nxt][get_col(v)].insert(v);
    }
}
void upd_small(int v, int x) {
    tt++;
    small_adj.clear();
    dfs_small(v);
 
    int new_size = sz[find_set(v)];
    for (auto nxt : small_adj) if (get_col(nxt) == x) {
        new_size += sz[find_set(nxt)];
    }
 
    if (new_size >= B) {
        make_big(v, true);
        upd_big(v, x);
    } else {
        for (auto nxt : small_adj) if (sz[find_set(nxt)] >= B) {
            adj_col[nxt][get_col(v)].erase(find_set(v));
        }
        for (auto add : small_adj) {
            if (get_col(add) == x) {
                clear_comp(add);
            }
        }
        for (auto add : small_adj) {
            if (get_col(add) == x) {
                union_sets(v, add);
            }
        }
        col[find_set(v)] = x;
        add_small(v);
    }
}
void upd(int i, int j, int x) {
    int v = i*m + j;
    if (sz[find_set(v)] >= B) upd_big(v, x);
    else upd_small(v, x);
}
 
int a[N];
void init() { // initially merge stuff
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            p[i*m + j] = i*m + j;
            sz[i*m + j] = 1;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> a[i*m + j];
            col[i*m + j] = a[i*m + j];
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = 0; k < 4; k++) {
                int ni = i + dx[k], nj = j + dy[k];
                if (ni < 0 || ni >= n || nj < 0 || nj >= m) continue;
                if (a[ni*m + nj] == a[i*m + j]) {
                    union_sets(i*m + j, ni*m + nj);
                }
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (p[i*m + j] == i*m + j && sz[find_set(i*m + j)] >= B) {
                make_big(i*m + j);
            }
        }
    }
}
void solve() {
    cin >> n >> m;

    init();

    int q; cin >> q;
    while (q--) {
        int i, j, x; cin >> i >> j >> x, --i, --j;
        upd(i, j, x);
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)
            cout << col[find_set(i*m + j)] << ' ';
        cout << '\n';
    }
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) solve();
}
# Verdict Execution time Memory Grader output
1 Correct 6 ms 11220 KB Output is correct
2 Correct 6 ms 11348 KB Output is correct
3 Correct 9 ms 11584 KB Output is correct
4 Correct 15 ms 11508 KB Output is correct
5 Correct 14 ms 13140 KB Output is correct
6 Correct 15 ms 11752 KB Output is correct
7 Correct 6 ms 11220 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 46 ms 12484 KB Output is correct
2 Correct 240 ms 13896 KB Output is correct
3 Correct 148 ms 29632 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 169 ms 32972 KB Output is correct
2 Correct 138 ms 25904 KB Output is correct
3 Correct 169 ms 30928 KB Output is correct
4 Correct 198 ms 23128 KB Output is correct
5 Correct 183 ms 23228 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 120 ms 17940 KB Output is correct
2 Correct 256 ms 40548 KB Output is correct
3 Correct 680 ms 31828 KB Output is correct
4 Correct 983 ms 34112 KB Output is correct
5 Correct 791 ms 27952 KB Output is correct
6 Correct 1061 ms 173532 KB Output is correct
7 Correct 757 ms 128336 KB Output is correct
8 Correct 550 ms 94728 KB Output is correct
9 Correct 595 ms 34540 KB Output is correct