#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 |
- |