Submission #1017044

#TimeUsernameProblemLanguageResultExecution timeMemory
1017044CodeAssignmentPaint (COI20_paint)C++17
9 / 100
755 ms350216 KiB
#include "bits/stdc++.h" #include <ext/pb_ds/assoc_container.hpp> using namespace std; using namespace __gnu_pbds; /* typedef tree<int,null_type,less<int>,rb_tree_tag, tree_order_statistics_node_update> indexed_set; */ #define el "\n" #define faster ios_base::sync_with_stdio(0); cin.tie(0); #define sq(x) (x)*(x) #define pb push_back #define mp make_pair #define F first #define S second #define sz(x) (int)(x).size() #define setcontains(set, x) (set.find(x) != set.end()) #define umap unordered_map #define uset unordered_set typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef vector<int> vi; typedef vector<pii> vpii; typedef vector<vi> vvi; typedef pair<ll,ll> pll; typedef vector<ll> vll; typedef vector<vll> vvll; typedef vector<pll> vpll; #define all(x) (x).begin(), (x).end() #define rep(i, a, b) for (int i = (a); i < (b); ++i) #define per(i, a, b) for (int i = (b-1); i >= (a); --i) #define REP(i, a, b) for (int i = (a); i <= (b); ++i) #define trav(a, x) for (auto &a : x) struct chash { // large odd number for C const uint64_t C = ll(4e18 * acos(0)) | 71; ll operator()(ll x) const { return __builtin_bswap64(x * C); } }; template<typename T> using fast_set = __gnu_pbds::gp_hash_table<T, null_type, chash>; template<typename T, typename H> using fast_set_h = __gnu_pbds::gp_hash_table<T, null_type, H>; template<typename T, typename U> using fast_map = __gnu_pbds::gp_hash_table<T, U, chash>; #ifdef DEBUg #include "/home/redkar/kod/cp/lib/debug.cpp" #else #define dbg(...) #define dbgArr(...) #endif const ll inf = 1e11; const ll heavy = 200; // TODO: try 30 vpll dirs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; ll r, c, q; ll get_ind(ll R, ll C) { if (0 <= R && R < r && 0 <= C && C < c) { return R*c + C; } else return -1; } /* dies here 3 3 2 1 3 2 2 5 2 2 4 3 2 2 3 2 2 5 2 2 3 */ struct UF { vll col, parent; vector<uset<ll>> edges; vector<umap<ll, uset<ll>>> buddy; vector<uset<ll>> heavybuddy; uset<ll> bigboys; UF(ll n, vll grid): col(n), parent(n), edges(n), buddy(n), heavybuddy(n) { rep(i, 0, n) { parent[i] = i; col[i] = grid[i]; } } ll find(ll x) { if (x != parent[x]) parent[x] = find(parent[x]); return parent[x]; } void reorganize() { // reorganize into heavy and not heavy rep(i, 0, r) rep(j, 0, c) { ll component = find(get_ind(i, j)); if (sz(edges[component]) >= heavy) { bigboys.insert(component); trav(COL, buddy[component]) { trav(nb, COL.S) { // TODO: what about adding the other way? Edit: I am not sure what I meant here buddy[nb][col[component]].erase(component); heavybuddy[nb].insert(component); } } trav(nb, heavybuddy[component]) { buddy[nb][col[component]].erase(component); /* hopefully this doesnt cause runtime error */ heavybuddy[nb].insert(component); } } } } void merge(ll a, ll b) { a = find(a); b = find(b); if (a == b) return; //if (mass[a] < mass[b]) swap(a, b); //mass[a] += mass[b]; parent[b] = a; } void bucket(ll node, ll C) { ll oldColor = col[node]; col[node] = C; dbg(node, C); dbg(parent); dbg(buddy); dbg(edges); ll mx = 0; ll bst = node; uset<ll> compnodes; /* finding bst vvvvvv */ dbg(buddy[node][C]); trav(nb, buddy[node][C]) { assert(col[nb] == C); compnodes.insert(nb); if (sz(edges[nb]) > mx) { mx = sz(edges); bst = nb; } } buddy[node][C].clear(); trav(nb, heavybuddy[node]) { if (col[nb] != C) continue; compnodes.insert(nb); if (sz(edges[nb]) > mx) { mx = sz(edges); bst = nb; } } dbg(bst); dbg(col[bst]); compnodes.insert(node); dbg(compnodes); //if (setcontains(bigboys, node)) heavybuddy[bst].erase(node); //else buddy[bst][oldColor].erase(node); trav(nb, edges[node]) { dbg(nb); edges[nb].erase(node); if (setcontains(bigboys, node)) heavybuddy[nb].erase(node); else buddy[nb][oldColor].erase(node); } uset<ll> bstneighbors; trav(cnode, compnodes) { if (cnode == bst) continue; parent[cnode] = bst; edges[bst].erase(cnode); if (setcontains(bigboys, cnode)) { bigboys.erase(cnode); // TODO: are you allowed to remove something that doesn't exist from a set? heavybuddy[bst].erase(cnode); } else buddy[bst][C].erase(cnode); trav(COL, buddy[cnode]) { //if (COL.F == C) continue; trav(nb, COL.S) { // TODO: could edges exist in both buddy and heavybuddy? edges[nb].erase(cnode); if (setcontains(bigboys, cnode)) heavybuddy[nb].erase(cnode); else buddy[nb][C].erase(cnode); edges[bst].insert(nb); edges[nb].insert(bst); assert(!setcontains(bigboys, nb)); buddy[bst][col[nb]].insert(nb); bstneighbors.insert(nb); } } buddy[cnode].clear(); trav(nb, heavybuddy[cnode]) { if (setcontains(bigboys, cnode)) heavybuddy[nb].erase(cnode); else buddy[nb][C].erase(cnode); edges[bst].insert(nb); edges[nb].insert(bst); heavybuddy[bst].insert(nb); bstneighbors.insert(nb); assert(col[bst] == C); } buddy[cnode].clear(); heavybuddy[cnode].clear(); } trav(nb, edges[node]) { if (col[nb] == C) continue; edges[bst].insert(nb); edges[nb].insert(bst); if (setcontains(bigboys, nb)) heavybuddy[bst].insert(nb); else buddy[bst][col[nb]].insert(nb); bstneighbors.insert(nb); } if (node != bst) edges[node].clear(); dbg(bstneighbors); /* if (node != bst) { buddy[node][C].clear(); heavybuddy[node].clear(); } */ // TODO: this just adds to bigboys, not removes if (sz(edges[bst]) >= heavy) { bigboys.insert(bst); trav(nb, bstneighbors) { heavybuddy[nb].insert(bst); } } else { bigboys.erase(bst); trav(nb, bstneighbors) { buddy[nb][C].insert(bst); } } } }; void solve() { cin >> r >> c; //assert(r * c <= 10000); vll grid(r*c); rep(i, 0, r*c) { cin >> grid[i]; } UF uf(r*c, grid); //dbg(1); rep(phase, 0, 2) { //dbg(phase); rep(i, 0, r) rep(j, 0, c) { ll cell = get_ind(i, j); ll cell_leader = uf.find(cell); //ll cell_color = uf.col[uf.find(cell)]; trav(d, dirs) { ll y = i + d.F, x = j + d.S; if (y < 0 || y >= r || x < 0 || x >= c) continue; ll nb_cell = get_ind(y, x); ll nb_leader = uf.find(nb_cell); if (grid[cell] == grid[nb_cell] && phase == 0) { uf.merge(cell, nb_cell); } else if (grid[cell] != grid[nb_cell] && phase == 1) { uf.buddy[cell_leader][uf.col[nb_leader]].insert(nb_leader); uf.buddy[nb_leader][uf.col[cell_leader]].insert(cell_leader); uf.edges[cell_leader].insert(nb_leader); uf.edges[nb_leader].insert(cell_leader); } } } } dbg(uf.col); //dbg(uf.buddy); uf.reorganize(); dbg(uf.col); //dbg(uf.buddy); cin >> q; while(q--) { ll y, x, C; cin >> y >> x >> C; y--, x--; //dbg(y, x, C); ll cur = uf.find(get_ind(y, x)); if (uf.col[cur] != C) { uf.bucket(cur, C); } /* rep(i, 0, r) { cerr << "temp: "; rep(j, 0, c) { cerr << uf.col[uf.find(get_ind(i, j))] << " "; } cerr << el; } */ } rep(i, 0, r) { rep(j, 0, c) { cout << uf.col[uf.find(get_ind(i, j))] << " "; } cout << el; } } int main() { faster int test = 1; // cin >> test; REP(tc, 1, test) { solve(); } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...