#include #pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2,popcnt") #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TP template #define TN typename #define TE TP #define TES TP #define Z auto #define var const Z & #define ep emplace_back #define eb emplace #define fi first #define se second #define bg begin #define ed end #define all(x) bg(x), ed(x) #define OV(a, b, c, d, e, ...) e #define FO4(i, a, b, c) for (int i = (a); i < (b); i += (c)) #define FO3(i, a, b) FO4(i, a, b, 1) #define FO2(i, a) FO3(i, 0, a) #define FO1(a) FO2(_, a) #define FOR(...) OV(__VA_ARGS__, FO4, FO3, FO2, FO1)(__VA_ARGS__) #define FF4(i, a, b, c) for (int i = (b) - 1; i >= (a); i -= (c)) #define FF3(i, a, b) FF4(i, a, b, 1) #define FF2(i, a) FF3(i, 0, a) #define FF1(a) FF2(_, a) #define FOR_R(...) OV(__VA_ARGS__, FF4, FF3, FF2, FF1)(__VA_ARGS__) #define FOR_subset(t, s) for (int t = (s); t > -1; t = (t == 0 ? -1 : (t - 1) & s)) #define sort ranges::sort using namespace std; TE using vc = vector; TE using vvc = vc>; TE using T1 = tuple; TE using T2 = tuple; TE using T3 = tuple; TE using T4 = tuple; TE using max_heap = priority_queue; TE using min_heap = priority_queue, greater>; using u8 = unsigned char; using uint = unsigned int; using ll = long long; using ull = unsigned long long; using ld = long double; using i128 = __int128; using u128 = __uint128_t; using f128 = __float128; using u16 = uint16_t; using PII = pair; using PLL = pair; using vi = vc; using vl = vc; #ifdef YRSD constexpr bool dbg = 1; #else constexpr bool dbg = 0; #endif TES concept nof = (not same_as and ...); TE constexpr bool can_in = 0; TE constexpr bool can_out = 0; TP<> constexpr bool can_in = 1; TP<> constexpr bool can_out = 1; istream &operator>>(istream &I, i128 &x) { static string s; I >> s; int f = s[0] == '-'; x = 0; const int N = (int)s.size(); FOR(i, f, N) x = x * 10 + s[i] - '0'; if (f) x = -x; return I; } ostream &operator<<(ostream &O, i128 x) { static string s; s.clear(); bool f = x < 0; if (f) x = -x; while (x) s += '0' + x % 10, x /= 10; if (s.empty()) s += '0'; if (f) s += '-'; reverse(all(s)); return O << s; } istream &operator>>(istream &I, f128 &x) { static string s; I >> s, x = stold(s); return I; } ostream &operator<<(ostream &O, const f128 x) { return O << ld(x); } TP requires(can_in) I &operator>>(I &in, tuple &a) { apply([&in](Z &...s) { ((in >> s), ...); }, a); return in; } TP requires(can_in) I &operator>>(I &in, pair &x) { return in >> x.fi >> x.se; } TP requires(can_out) U &operator<<(U &out, const pair &x) { return out << x.fi << ' ' << x.se; } TP requires(can_in) I &operator>>(I &in, vc &a) { for (Z &x : a) in >> x; return in; } TP requires(can_out) U &operator<<(U &out, const vc &a) { if (a.empty()) return out; Z i = bg(a); out << *i++; for (; i != ed(a); ++i) out << ' ' << *i; return out; } TP requires(can_in) I &operator>>(I &in, array &a) { FOR(i, N) in >> a[i]; return in; } TP requires(can_out) U &operator<<(U &out, const array &a) { out << a[0]; FOR(i, 1, N) out << ' ' << a[i]; return out; } void IN() {} TE void IN(T &x, Z &...s) { cin >> x, IN(s...); } void print() { cout << '\n'; } TES void print(T &&x, S &&...y) { cout << x; if constexpr (sizeof...(S)) cout << ' '; print(forward(y)...); } void put() {} TES void put(T &&x, S &&...y) { cout << x; put(forward(y)...); } #define INT(...) int __VA_ARGS__; IN(__VA_ARGS__) #define UINT(...) uint __VA_ARGS__; IN(__VA_ARGS__) #define LL(...) ll __VA_ARGS__; IN(__VA_ARGS__) #define ULL(...) ull __VA_ARGS__; IN(__VA_ARGS__) #define I128(...) i128 __VA_ARGS__; IN(__VA_ARGS__) #define STR(...) string __VA_ARGS__; IN(__VA_ARGS__) #define CH(...) char __VA_ARGS__; IN(__VA_ARGS__) #define REAL(...) re __VA_ARGS__; IN(__VA_ARGS__) #define VEC(T, a, n) vc a(n); IN(a) void YES(bool o = 1) { print(o ? "YES" : "NO"); } void Yes(bool o = 1) { print(o ? "Yes" : "No"); } void yes(bool o = 1) { print(o ? "yes" : "no"); } void NO(bool o = 1) { YES(not o); } void No(bool o = 1) { Yes(not o); } void no(bool o = 1) { yes(not o); } void ALICE(bool o = 1) { print(o ? "ALICE" : "BOB"); } void Alice(bool o = 1) { print(o ? "Alice" : "Bob"); } void alice(bool o = 1) { print(o ? "alice" : "bob"); } void BOB(bool o = 1) { ALICE(not o); } void Bob(bool o = 1) { Alice(not o); } void bob(bool o = 1) { alice(not o); } void POSSIBLE(bool o = 1) { print(o ? "POSSIBLE" : "IMPOSSIBLE"); } void Possible(bool o = 1) { print(o ? "Possible" : "Impossible"); } void possible(bool o = 1) { print(o ? "possible" : "impossible"); } void IMPOSSIBLE(bool o = 1) { POSSIBLE(not o); } void Impossible(bool o = 1) { Possible(not o); } void impossible(bool o = 1) { possible(not o); } void TAK(bool o = 1) { print(o ? "TAK" : "NIE"); } void NIE(bool o = 1) { TAK(not o); } #if (__cplusplus >= 202002L) #include constexpr ld pi = numbers::pi_v; #endif TE constexpr T inf = numeric_limits::max(); template <> constexpr i128 inf = i128(inf) * 2'000'000'000'000'000'000; template constexpr pair inf> = {inf, inf}; TE constexpr static inline int pc(T x) { return popcount(make_unsigned_t(x)); } constexpr static inline ll si(var a) { return a.size(); } void reverse(Z &a) { reverse(all(a)); } void unique(Z &a) { sort(a); a.erase(unique(all(a)), ed(a)); } TE vc inverse(const vc &a) { int N = si(a); vc b(N, -1); FOR(i, N) if (a[i] != -1) b[a[i]] = i; return b; } Z QMAX(var a) { return *max_element(all(a)); } Z QMIN(var a) { return *min_element(all(a)); } TE Z QMAX(T l, T r) { return *max_element(l, r); } TE Z QMIN(T l, T r) { return *min_element(l, r); } constexpr bool chmax(Z &a, var b) { return (a < b ? a = b, 1 : 0); } constexpr bool chmin(Z &a, var b) { return (a > b ? a = b, 1 : 0); } vc argsort(var a) { vc I(si(a)); iota(all(I), 0); sort(I, [&](int i, int k) { return a[i] < a[k] or (a[i] == a[k] and i < k); }); return I; } TE vc rearrange(const vc &a, const vc &I) { int N = si(I); vc b(N); FOR(i, N) b[i] = a[I[i]]; return b; } template vc pre_sum(const vc &a) { int N = si(a); vc c(N + 1); FOR(i, N) c[i + 1] = c[i] + a[i]; if (of == 0) c.erase(bg(c)); return c; } TE constexpr static int topbit(T x) { if (x == 0) return -1; if constexpr (sizeof(T) <= 4) return 31 - __builtin_clz(x); else return 63 - __builtin_clzll(x); } TE constexpr static int lowbit(T x) { if (x == 0) return -1; if constexpr (sizeof(T) <= 4) return __builtin_ctz(x); else return __builtin_ctzll(x); } TE constexpr inline T floor(T x, T y) { return x / y - (x % y and (x ^ y) < 0); } TE constexpr inline T ceil(T x, T y) { return floor(x + y - 1, y); } TE constexpr inline T bmod(T x, T y) { return x - floor(x, y) * y; } TE constexpr inline pair divmod(T x, T y) { T q = floor(x, y); return pair{q, x - q * y}; } TE T SUM(var v) { return accumulate(all(v), T()); } TE T SUM(Z l, Z r) { return accumulate(l, r, T()); } int lb(var a, Z x) { return lower_bound(all(a), x) - a.begin(); } TE int lb(T l, T r, Z x) { return lower_bound(l, r, x) - l; } int ub(var a, Z x) { return upper_bound(all(a), x) - a.begin(); } TE int ub(T l, T r, Z x) { return upper_bound(l, r, x) - l; } template ll bina(Z f, ll l, ll r) { if (ck) assert(f(l)); while (abs(l - r) > 1) { ll x = (r + l) >> 1; (f(x) ? l : r) = x; } return l; } TE T bina_real(Z f, T l, T r, int c = 100) { while (c--) { T x = (l + r) / 2; (f(x) ? l : r) = x; } return (l + r) / 2; } TE T pop(vc &a) { T x = a.back(); a.pop_back(); return x; } TE T pop(max_heap &q) { T x = q.top(); q.pop(); return x; } TE T pop(min_heap &q) { T x = q.top(); q.pop(); return x; } char pop(string &s) { char x = s.back(); s.pop_back(); return x; } void setp(int x) { cout << fixed << setprecision(x); } TE inline void sh(vc &a, int N, T b = {}) { a.resize(N, b); } #ifdef MeIoN void DBG() { cerr << "]" << endl; } TES void DBG(T &&x, S &&...y) { cerr << x; if constexpr (sizeof...(S)) cerr << ", "; DBG(forward(y)...); } #define debug(...) cerr << "[" << __LINE__ << "]: [" #__VA_ARGS__ "] = [", DBG(__VA_ARGS__) void ERR() { cerr << endl; } TES void ERR(T &&x, S &&...y) { cerr << x; if constexpr (sizeof...(S)) cerr << ", "; ERR(forward(y)...); } #define err(...) cerr << "[" << __LINE__ << "]: ", ERR(__VA_ARGS__) #else #define debug(...) void(0721) #define err(...) void(0721) #endif namespace fio { static constexpr uint sz = 1 << 17; char a[sz]; char b[sz]; char t[100]; uint l = 0, r = 0, pr = 0; struct Pre { char num[10000][4]; constexpr Pre() : num() { for (int i = 0; i < 10000; i++) { int n = i; for (int j = 3; j >= 0; j--) { num[i][j] = n % 10 | '0'; n /= 10; } } } } constexpr pre; inline void load() { memcpy(a, a + l, r - l); r = r - l + fread(a + r - l, 1, sz - r + l, stdin); l = 0; if (r < sz) a[r++] = '\n'; } inline void flush() { fwrite(b, 1, pr, stdout), pr = 0; } inline void rd(char &c) { do { if (l + 1 > r) load(); c = a[l++]; } while (isspace(c)); } inline void rd(string &s) { s.clear(); char c; do { if (l + 1 > r) load(); c = a[l++]; } while (isspace(c)); do { s += c; if (l == r) load(); c = a[l++]; } while (!isspace(c)); } TE inline void rd_re(T &x) { static string s; rd(s); x = stod(s); } TE inline void rd_inte(T &x) { if (l + 100 > r) load(); char c; do c = a[l++]; while (c < '-'); bool op = 0; if constexpr (is_signed_v or is_same_v) { if (c == '-') op = 1, c = a[l++]; } x = 0; while ('0' <= c) x = x * 10 + (c & 15), c = a[l++]; if constexpr (is_signed_v or is_same_v) { if (op) x = -x; } } struct Fin { inline Fin &operator>>(char &c) { rd(c); return *this; } inline Fin &operator>>(string &s) { rd(s); return *this; } TE requires(is_integral_v or is_same_v or is_same_v) inline Fin &operator>>(T &x) { rd_inte(x); return *this; } TE requires(is_floating_point_v or is_same_v) inline Fin &operator>>(T &x){ rd_re(x); return *this; } } fin; inline void wt(char c) { if (pr == sz) flush(); b[pr++] = c; } inline void wt(const string &s) { for (char c : s) wt(c); } inline void wt(const char *s) { size_t si = strlen(s); for (size_t i = 0; i < si; i++) wt(s[i]); } TE inline void wt_inte(T x) { if (pr > sz - 100) flush(); if (x < 0) b[pr++] = '-', x = -x; int outi = 96; for (; x >= 10000; outi -= 4) { memcpy(t + outi, pre.num[x % 10000], 4); x /= 10000; } if (x >= 1000) { memcpy(b + pr, pre.num[x], 4); pr += 4; } else if (x >= 100) { memcpy(b + pr, pre.num[x] + 1, 3); pr += 3; } else if (x >= 10) { int q = (x * 103) >> 10; b[pr] = q | '0'; b[pr + 1] = (x - q * 10) | '0'; pr += 2; } else b[pr++] = x | '0'; memcpy(b + pr, t + outi + 4, 96 - outi); pr += 96 - outi; } int w = 10; TE inline void wt_real(T x) { ostringstream oss; oss << fixed << setprecision(w) << double(x); string s = oss.str(); wt(s); } struct Fout { void setp(int x) { w = x; } inline Fout &operator<<(const char &c) { wt(c); return *this; } inline Fout &operator<<(const string &s) { wt(s); return *this; } TE requires(is_integral_v or is_same_v or is_same_v) inline Fout &operator<<(const T &x) { wt_inte(x); return *this; } TE requires(is_floating_point_v or is_same_v) inline Fout &operator<<(const T &x) { wt_real(x); return *this; } } fout; inline void __attribute__((destructor)) _d() { flush(); } inline void sc() {} TE inline void sc(T &x, Z &...s) { fin >> x, sc(s...); } void inline pt() { fout << '\n'; } TES inline void pt(T &&x, S &&...y) { fout << x; if constexpr (sizeof...(S)) fout << ' '; pt(forward(y)...); } void inline pu() {} TES inline void pu(T &&x, S &&...y) { fout << x; pu(forward(y)...); } } template <> constexpr bool can_in = 1; template <> constexpr bool can_out = 1; #define setp(x) fio::fout.setp(x) #define IN fio::sc #define print fio::pt #define put fio::pu TE struct retsu { int N, M; vc a; retsu(int N, int M, T bs = T()) : N(N), M(M), a(N * M, bs) {} T* operator[](int i) { return a.data() + i * M; } const T* operator[](int i) const { return a.data() + i * M; } void fill(T x) { std::fill(all(a), x); } void build(int n, int m, T bs = T()) { N = n, M = m; a.assign(N * M, bs); } inline int id(int x, int y) const { return x * M + y; } retsu rol() const { retsu c(M, N); FOR(i, N) FOR(k, M) c[k][i] = a[id(i, k)]; return c; } retsu rol90() const { retsu c(M, N); FOR(i, N) FOR(k, M) c[k][i] = a[id(i, M - k - 1)]; return c; } void pres() { FOR(i, 1, N) FOR(k, M) a[id(i, k)] += a[id(i - 1, k)]; FOR(i, N) FOR(k, 1, M) a[id(i, k)] += a[id(i, k - 1)]; } inline T prod(int x, int y) const { return a[id(x, y)]; } inline T prod(int l, int r, int a, int b) const { return prod(r, b) + prod(l, a) - prod(l, b) - prod(r, a); } T max() const { return QMAX(a); } T min() const { return QMIN(a); } void reverse() { FOR(i, N) FOR(k, M >> 1) swap(a[i * M + k], a[i * M + M - k - 1]); } vc> to_v() const { vector c(N, vc(M)); FOR(i, N) FOR(k, M) c[i][k] = a[id(i, k)]; return c; } }; TP requires(can_in) I &operator>>(I &cin, retsu &a) { for (Z &e : a.a) cin >> e; return cin; } TP requires(can_out) U &operator<<(U &cout, const retsu &a) { FOR(i, a.N) { FOR(k, a.M) { if (k) cout << ' '; cout << a[i][k]; } if (i + 1 != a.N) cout << '\n'; } return cout; } struct dsu { int c; vc fa; dsu(int N = 0) : c(N), fa(N, -1) {} int f(int x) { while (fa[x] >= 0) { int p = fa[fa[x]]; if (p < 0) return fa[x]; x = fa[x] = p; } return x; } int operator[](int x) { return f(x); } bool merge(int x, int y) { x = f(x), y = f(y); if (x == y) return 0; if (fa[x] > fa[y]) swap(x, y); fa[x] += fa[y]; fa[y] = x; --c; return 1; } bool set(int x, int y) { x = f(x), y = f(y); if (x == y) return 0; fa[x] += fa[y]; fa[y] = x; --c; return 1; } int size(int x) { return -fa[f(x)]; } int count() const { return c; } bool same(int x, int y) { return f(x) == f(y); } void build(int N) { fa.assign(N, -1), c = N; } void reset() { fill(all(fa), -1), c = si(fa); } vc> group() { int N = si(fa); vc> v(N), s; FOR(i, N) v[f(i)].ep(i); FOR(i, N) if (not v[i].empty()) s.ep(v[i]); return s; } void pr() { int N = si(fa); vc res(N); FOR(i, N) res[i] = f(i); print("fa:", res); } }; void Yorisou() { INT(N, M); retsu id(N, M); vc c(N * M); FOR(i, N) FOR(k, M) { INT(x); c[i * M + k] = x; } dsu g(N * M); iota(all(id.a), 0); FOR(i, N) FOR(k, M) { if (i and c[g[id[i][k]]] == c[g[id[i - 1][k]]]) g.merge(id[i][k], id[i - 1][k]); if (k and c[g[id[i][k]]] == c[g[id[i][k - 1]]]) g.merge(id[i][k], id[i][k - 1]); } vc se; FOR(i, N) FOR(k, M) { if (i and c[g[id[i][k]]] != c[g[id[i - 1][k]]]) se.ep(id[i][k], id[i - 1][k]); if (k and c[g[id[i][k]]] != c[g[id[i][k - 1]]]) se.ep(id[i][k], id[i][k - 1]); } INT(Q); FOR(Q) { INT(x, y, a); --x, --y; c[g[id[x][y]]] = a; if (g.c == 1) continue; FOR_R(j, si(se)) { var [i, k] = se[j]; if (c[g[i]] == c[g[k]]) { g.merge(i, k); se.erase(bg(se) + j); } } } FOR(i, N) FOR(k, M) { put((int)c[g[id[i][k]]], " \n"[k + 1 == M]); } } int main() { Yorisou(); return 0; }