답안 #1017044

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1017044 2024-07-08T19:09:00 Z CodeAssignment Paint (COI20_paint) C++17
9 / 100
755 ms 350216 KB
#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();
	}
}


# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 1112 KB Output is correct
2 Correct 2 ms 1372 KB Output is correct
3 Correct 30 ms 17876 KB Output is correct
4 Runtime error 40 ms 23892 KB Execution killed with signal 6
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 239 ms 53664 KB Output is correct
2 Correct 223 ms 62532 KB Output is correct
3 Correct 407 ms 120372 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Runtime error 339 ms 338292 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 755 ms 350216 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -