제출 #1323901

#제출 시각아이디문제언어결과실행 시간메모리
1323901cpismylifeOwOPaint (COI20_paint)C++20
0 / 100
535 ms589824 KiB
#include <bits/stdc++.h>

using namespace std;

const long long mod = 1e9 + 7;
const int MaxN = 2e5 + 5;
const int BlockSize = 447;

int r, s, q, mx;
vector<vector<int>> arr;

void Inp()
{
    cin >> r >> s;
    mx = 0;
    arr.resize(r + 1);
    arr[0].resize(s + 1);
    for (int x = 1; x <= r; x++)
    {
        arr[x].resize(s + 1);
        for (int y = 1; y <= s; y++)
        {
            cin >> arr[x][y];
            mx = max(mx, arr[x][y]);
        }
    }
}

int Hash(int x, int y)
{
    return (x - 1) * s + y;
}

bool CheckX(int a)
{
    return 1 <= a && a <= r;
}

bool CheckY(int a)
{
    return 1 <= a && a <= s;
}

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
vector<vector<bool>> visited;
vector<pair<int, int>> tmpnow;

void DFS(int a, int b)
{
    visited[a][b] = true;
    tmpnow.push_back(make_pair(a, b));
    for (int x = 0; x < 4; x++)
    {
        int newa = a + dx[x], newb = b + dy[x];
        if (CheckX(newa) && CheckY(newb) && !visited[newa][newb] && arr[newa][newb] == arr[a][b])
        {
            DFS(newa, newb);
        }
    }
}

int curBig;
int parents[MaxN];
int isbig[MaxN];
int curcolor[MaxN];
vector<pair<int, int>> lst[MaxN];
vector<int> mrkbig[MaxN / BlockSize + 5][MaxN / 2];
vector<int> mrksmall[MaxN];

int FindSet(int p)
{
    if (parents[p] == p)
    {
        return p;
    }
    parents[p] = FindSet(parents[p]);
    return parents[p];
}

bool tmp[MaxN];
bool tmp2[MaxN];

void UnionSet(int a, int b)
{
    a = FindSet(a);
    b = FindSet(b);
    if (a == b)
    {
        return;
    }
    if ((int)lst[a].size() < (int)lst[b].size())
    {
        swap(a, b);
    }
    bool isa = !isbig[a], isb = !isbig[b];
    if (isa && isb)
    {
        int ua = isbig[a], ub = isbig[b];
        for (int x = 0; x <= mx; x++)
        {
            for (int y : mrkbig[ua][x])
            {
                tmp[y] = true;
            }
            for (int y : mrkbig[ub][x])
            {
                if (!tmp[y])
                {
                    tmp[y] = true;
                    mrkbig[ua][x].push_back(y);
                }
            }
            for (int y : mrkbig[ua][x])
            {
                tmp[y] = false;
            }
            mrkbig[ub][x].clear();
        }
    }
    else if (isb)
    {
        for (pair<int, int> x : lst[b])
        {
            for (int t = 0; t < 4; t++)
            {
                int newa = x.first + dx[t], newb = x.second + dy[t];
                if (CheckX(newa) && CheckY(newb))
                {
                    int newu = FindSet(Hash(newa, newb));
                    if (newu != a && newu != b)
                    {
                        mrkbig[isbig[a]][curcolor[newu]].push_back(newu);
                    }
                }
            }
        }
    }
    parents[b] = a;
    for (pair<int, int> x : lst[b])
    {
        lst[a].push_back(x);
    }
    lst[b].clear();
    for (int x = 0; x < (int)mrksmall[a].size(); x++)
    {
        if (mrksmall[a][x] == b)
        {
            swap(mrksmall[a][x], mrksmall[a].back());
            mrksmall[a].pop_back();
            x--;
        }
    }
    for (int x : mrksmall[a])
    {
        tmp[x] = true;
    }
    for (int x : mrksmall[b])
    {
        if (!tmp[x] && x != a)
        {
            mrksmall[a].push_back(x);
            tmp[x] = true;
        }
    }
    for (int x : mrksmall[a])
    {
        tmp[x] = false;
    }
}

void ChangeBig(int u, int c)
{
    curcolor[u] = c;
    for (int x : mrkbig[isbig[u]][c])
    {
        if (curcolor[FindSet(x)] == c && (int)lst[FindSet(x)].size() <= BlockSize)
        {
            UnionSet(u, x);
        }
    }
    mrkbig[isbig[u]][c].clear();
    vector<int> out;
    for (int x : mrksmall[u])
    {
        if (curcolor[FindSet(x)] == c)
        {
            out.push_back(x);
        }
    }
    for (int x : out)
    {
        UnionSet(u, x);
    }
}

void ChangeSmall(int u, int c)
{
    curcolor[u] = c;
    vector<int> out, plc;
    for (pair<int, int> x : lst[u])
    {
        for (int y = 0; y < 4; y++)
        {
            int newa = x.first + dx[y], newb = x.second + dy[y];
            if (CheckX(newa) && CheckY(newb))
            {
                int newu = FindSet(Hash(newa, newb));
                if (tmp[newu])
                {
                    continue;
                }
                if (u != newu && curcolor[newu] == c)
                {
                    tmp[newu] = true;
                    out.push_back(newu);
                }
                else if (isbig[newu])
                {
                    tmp[newu] = true;
                    plc.push_back(newu);
                }
            }
        }
    }
    for (int x : out)
    {
        UnionSet(u, x);
    }
    u = FindSet(u);
    if ((int)lst[u].size() > BlockSize)
    {
        curBig++;
        isbig[u] = curBig;
        vector<int> out;
        for (pair<int, int> x : lst[u])
        {
            for (int y = 0; y < 4; y++)
            {
                int newa = x.first + dx[y], newb = x.second + dy[y];
                if (CheckX(newa) && CheckY(newb) && FindSet(Hash(newa, newb)) != u)
                {
                    int newu = FindSet(Hash(newa, newb));
                    if (tmp2[newu])
                    {
                        continue;
                    }
                    tmp2[newu] = true;
                    out.push_back(newu);
                    if ((int)lst[newu].size() <= BlockSize)
                    {
                        mrkbig[isbig[u]][curcolor[newu]].push_back(newu);
                    }
                    else
                    {
                        mrksmall[u].push_back(newu);
                        mrksmall[newu].push_back(u);
                    }
                }
            }
        }
        for (int x : out)
        {
            tmp2[x] = false;
        }
    }
    else
    {
        for (int x : plc)
        {
            mrkbig[isbig[x]][c].push_back(u);
        }
    }
    for (int x : out)
    {
        tmp[x] = false;
    }
    for (int x : plc)
    {
        tmp[x] = false;
    }
}

void Exc()
{
    visited.resize(r + 1);
    for (int x = 0; x <= r; x++)
    {
        visited[x].resize(s + 1);
    }
    curBig = 0;
    for (int x = 1; x <= r; x++)
    {
        for (int y = 1; y <= s; y++)
        {
            if (!visited[x][y])
            {
                tmpnow.clear();
                DFS(x, y);
                int u = Hash(x, y);
                for (pair<int, int> z : tmpnow)
                {
                    parents[Hash(z.first, z.second)] = u;
                    lst[u].push_back(z);
                }
                curcolor[u] = arr[x][y];
                if ((int)tmpnow.size() > BlockSize)
                {
                    curBig++;
                    isbig[u] = curBig;
                }
            }
        }
    }
    for (int x = 1; x <= r; x++)
    {
        for (int y = 1; y <= s; y++)
        {
            if (parents[Hash(x, y)] == Hash(x, y))
            {
                int u = Hash(x, y);
                set<int> out;
                for (pair<int, int> z : lst[u])
                {
                    for (int t = 0; t < 4; t++)
                    {
                        int newa = z.first + dx[t], newb = z.second + dy[t];
                        if (CheckX(newa) && CheckY(newb) && FindSet(Hash(newa, newb)) != u)
                        {
                            out.insert(FindSet(Hash(newa, newb)));
                        }
                    }
                }
                if ((int)lst[u].size() <= BlockSize)
                {
                    for (int x : out)
                    {
                        if ((int)lst[x].size() > BlockSize)
                        {
                            mrksmall[u].push_back(x);
                        }
                    }
                }
                else
                {
                    for (int x : out)
                    {
                        if ((int)lst[x].size() <= BlockSize)
                        {
                            mrkbig[isbig[u]][curcolor[x]].push_back(x);
                        }
                        else
                        {
                            mrksmall[u].push_back(x);
                        }
                    }
                }
            }
        }
    }
    cin >> q;
    for (int x = 1; x <= q; x++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        int u = Hash(a, b);
        u = FindSet(u);
        if (isbig[u])
        {
            ChangeBig(u, c);
        }
        else
        {
            ChangeSmall(u, c);
        }
    }
    for (int x = 1; x <= r; x++)
    {
        for (int y = 1; y <= s; y++)
        {
            cout << curcolor[FindSet(Hash(x, y))] << " ";
        }
        cout << "\n";
    }
}

int main()
{
    //freopen("PAINT.INP", "r", stdin);
    //freopen("PAINT.OUT", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int test = 1;
    //cin >> test;
    for (int x = 1; x <= test; x++)
    {
        Inp();
        Exc();
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...