답안 #393405

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
393405 2021-04-23T11:22:15 Z VEGAnn Paint (COI20_paint) C++14
69 / 100
3000 ms 62236 KB
#include <bits/stdc++.h>
#define ft first
#define sd second
#define PB push_back
#define sz(x) ((int)x.size())
#define i2 array<int,2>
using namespace std;
const int N = 200100;
const int BLOCK = 400;

vector<i2> elms;
bool init_mrk[N];
int n, m, pre[N];
int c[N], who[N];

int used[N], tt = 0;
int stp[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};

struct comp{
    int color;
    vector<i2> pnts;
    vector<int> big_neib;
    bool large;
    map<int, vector<int> > by_color;
};

vector<comp> comps;

int get_pre(int x) { return (pre[x] == x ? x : pre[x] = get_pre(pre[x])); }

void init_dfs(int x, int y, int now){
    if (x < 0 || y < 0 || x >= n || y >= m) return;
    if (init_mrk[x * m + y]) return;
    if (c[x * m + y] != now) return;

    elms.PB({x, y});
    init_mrk[x * m + y] = 1;
    who[x * m + y] = sz(comps);

    for (int it = 0; it < 4; it++){
        int cx = x + stp[it][0];
        int cy = y + stp[it][1];

        init_dfs(cx, cy, now);
    }
}

void declare_big(comp &now){
    now.large = 1;

    tt++;

    for (i2 CR : now.pnts){
        int x = CR[0], y = CR[1];

        int cur_comp = who[x * m + y];

        for (int it = 0; it < 4; it++){
            int cx = x + stp[it][0];
            int cy = y + stp[it][1];

            if (cx < 0 || cy < 0 || cx >= n || cy >= m) continue;

            int co_id = who[cx * m + cy];

            if (used[co_id] < tt){
                used[co_id] = tt;
                comps[co_id].big_neib.PB(cur_comp);
                comps[cur_comp].by_color[comps[co_id].color].PB(co_id);
            }
        }
    }
}

void Init(){
    cin >> n >> m;

    for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        cin >> c[i * m + j];

    for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++){
        if (init_mrk[i * m + j]) continue;

        elms.clear();

        init_dfs(i, j, c[i * m + j]);

        comp new_comp;

        new_comp.color = c[i * m + j];
        new_comp.pnts = elms;
        new_comp.large = 0;

        new_comp.big_neib.clear();
        new_comp.by_color.clear();

        comps.PB(new_comp);
    }

    for (int i = 0; i < n * m; i++)
        pre[i] = i;

    for (int i = 0; i < sz(comps); i++)
        if (sz(comps[i].pnts) > BLOCK)
            declare_big(comps[i]);
}

void merge(int c1, int c2){
    c1 = get_pre(c1);
    c2 = get_pre(c2);

    assert(c1 != c2);

    if (sz(comps[c1].pnts) < sz(comps[c2].pnts))
        swap(c1, c2);

    comp &fi = comps[c1];
    comp &se = comps[c2];

    if (fi.large && !se.large)
        declare_big(se);

    if (se.large && !fi.large)
        declare_big(fi);

    {
        /// update pnts

        pre[c2] = c1;

        for (i2 CR : se.pnts){
            int x = CR[0], y = CR[1];

            fi.pnts.PB(CR);
            who[x * m + y] = c1;
        }

        vector<i2> ().swap(se.pnts);
    }

    {
        /// update big_neib

        vector<int> nw_big;

        nw_big.clear();

        tt++;

        for (int cr : fi.big_neib){
            cr = get_pre(cr);

            if (used[cr] < tt) {
                nw_big.PB(cr);
                used[cr] = tt;
            }
        }

        for (int cr : se.big_neib){
            cr = get_pre(cr);

            if (used[cr] < tt) {
                nw_big.PB(cr);
                used[cr] = tt;
            }
        }

        vector<int> ().swap(fi.big_neib);
        vector<int> ().swap(se.big_neib);

        fi.big_neib.swap(nw_big);
    }

    if (fi.large) {
        /// update by_color

        if (sz(fi.by_color) < sz(se.by_color))
            fi.by_color.swap(se.by_color);

        for (auto cr : se.by_color){
            int col = cr.ft;
            vector<int> &sml = cr.sd;
            vector<int> &big = fi.by_color[col];

            if (sz(sml) > sz(big))
                sml.swap(big);

            for (int cr : sml)
                big.PB(cr);

            vector<int> ().swap(sml);
        }
    }

    if (!fi.large && sz(fi.pnts) > BLOCK)
        declare_big(fi);
}

void Fill(int x, int y, int nw_col){
    int cur_comp = who[x * m + y];

    comps[cur_comp].color = nw_col;

    if (sz(comps[cur_comp].pnts) > BLOCK){
        tt++;

        vector<int> nw;
        nw.clear();

        used[cur_comp] = tt;

        for (int co_id : comps[cur_comp].by_color[nw_col]){
            co_id = get_pre(co_id);

            if (used[co_id] < tt && comps[co_id].color == nw_col){
                nw.PB(co_id);
                used[co_id] = tt;
            }
        }

        for (int ids : nw)
            merge(cur_comp, ids);
    } else {
        tt++;

        vector<int> nw;
        nw.clear();

        used[cur_comp] = tt;

        for (i2 CR : comps[cur_comp].pnts){
            int X = CR[0], Y = CR[1];

            for (int it = 0; it < 4; it++){
                int cx = X + stp[it][0];
                int cy = Y + stp[it][1];

                if (cx < 0 || cy < 0 || cx >= n || cy >= m) continue;

                int co_id = who[cx * m + cy];

                if (used[co_id] < tt && comps[co_id].color == nw_col){
                    nw.PB(co_id);
                    used[co_id] = tt;
                }
            }
        }

        for (int ids : nw)
            merge(cur_comp, ids);
    }

    /// traverse big_neib and change color

    cur_comp = who[x * m + y];

    int col = comps[cur_comp].color;

    tt++;

    for (int cr : comps[cur_comp].big_neib){
        cr = get_pre(cr);

        if (used[cr] < tt) {
            comps[cr].by_color[col].PB(cur_comp);
            used[cr] = tt;
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);

#ifdef _LOCAL
    freopen("in.txt","r",stdin);
#endif // _LOCAL

    Init();

    int qq; cin >> qq;

    for (; qq; qq--){
        int x, y, col; cin >> x >> y >> col; x--; y--;

        Fill(x, y, col);
    }

    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            int co_id = who[i * m + j];

            cout << comps[co_id].color << " ";
        }
        cout << '\n';
    }

    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 460 KB Output is correct
2 Correct 1 ms 460 KB Output is correct
3 Correct 6 ms 2404 KB Output is correct
4 Correct 7 ms 1512 KB Output is correct
5 Correct 13 ms 2492 KB Output is correct
6 Correct 28 ms 1700 KB Output is correct
7 Correct 1 ms 332 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 72 ms 8924 KB Output is correct
2 Correct 136 ms 17604 KB Output is correct
3 Correct 278 ms 50760 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1570 ms 62236 KB Output is correct
2 Correct 438 ms 49448 KB Output is correct
3 Correct 517 ms 59868 KB Output is correct
4 Correct 2515 ms 46308 KB Output is correct
5 Execution timed out 3079 ms 38712 KB Time limit exceeded
# 결과 실행 시간 메모리 Grader output
1 Correct 176 ms 27648 KB Output is correct
2 Correct 508 ms 41472 KB Output is correct
3 Correct 709 ms 59136 KB Output is correct
4 Correct 538 ms 56572 KB Output is correct
5 Correct 678 ms 49040 KB Output is correct
6 Correct 227 ms 33680 KB Output is correct
7 Correct 220 ms 29480 KB Output is correct
8 Correct 209 ms 26336 KB Output is correct
9 Correct 699 ms 48964 KB Output is correct