// Author: Luka Kalinovcic #include #include #define MAX 2000 int R, C; int a[MAX][MAX]; int pos_r = 0, pos_c = 0; int jump[MAX]; int Fix(int x, int X) { return (x % X + X) % X; } int NextRow(int r, int c) { int next_row = -1; int max_value = -1; for (int rr = r - 1; rr <= r + 1; ++rr) { const int value = a[Fix(rr, R)][Fix(c + 1, C)]; if (value > max_value) { max_value = value; next_row = rr; } } return next_row; } int RunToFirstColumn(int r, int c) { do { r = Fix(NextRow(r, c++), R); } while (c < C); return r; } struct Interval { Interval() = default; Interval(int lo, int hi) : lo(lo), hi(hi) {} bool IsEmpty() const { return lo > hi; } int Size() const { return hi - lo + 1; } bool Contains(int x) const { return lo <= x && x <= hi; } int lo = std::numeric_limits::max(); int hi = std::numeric_limits::min(); }; void Update(int r, int c) { const int target_row = RunToFirstColumn(r, c); Interval rows(r, r); int cc = c; while (cc > 0) { --cc; Interval new_rows; for (int rr = rows.lo - 1; rr <= rows.lo + 1; ++rr) { if (rows.Contains(NextRow(rr, cc))) { new_rows.lo = rr; break; } } for (int rr = rows.hi + 1; rr >= rows.hi - 1; --rr) { if (rows.Contains(NextRow(rr, cc))) { new_rows.hi = rr; break; } } if (new_rows.IsEmpty()) return; rows = new_rows; } if (rows.Size() >= R) { for (int rr = 0; rr < R; ++rr) { jump[rr] = target_row; } } else { for (int rr = rows.lo; rr <= rows.hi; ++rr) { jump[Fix(rr, R)] = target_row; } } return; } void SuperWalk(int k) { static int walk_id = 0; static int last_walk_id[MAX]; static int last_k[MAX]; ++walk_id; if (k >= C - pos_c) { k -= C - pos_c; pos_r = RunToFirstColumn(pos_r, pos_c); pos_c = 0; } while (k >= C) { k -= C; pos_r = jump[pos_r]; if (last_walk_id[pos_r] == walk_id) { const int cycle_len = last_k[pos_r] - k; if (k >= cycle_len) { const int n_cycles = k / cycle_len; k -= n_cycles * cycle_len; } } last_walk_id[pos_r] = walk_id; last_k[pos_r] = k; } while (k--) { pos_r = Fix(NextRow(pos_r, pos_c++), R); } } int main() { scanf("%d%d", &R, &C); for (int r = 0; r < R; ++r) { for (int c = 0; c < C; ++c) { int k; scanf("%d", &k); a[r][c] = k; } } for (int r = 0; r < R; ++r) { jump[r] = RunToFirstColumn(r, 0); } int Q; scanf("%d", &Q); for (int qq = 0; qq < Q; ++qq) { static char command[16]; scanf("%s", command); if (command[0] == 'm') { int k; scanf("%d", &k); SuperWalk(k); printf("%d %d\n", pos_r + 1, pos_c + 1); } else { int r, c, k; scanf("%d%d%d", &r, &c, &k); --r; --c; a[r][c] = k; for (int rr = r - 1; rr <= r + 1; ++rr) { Update(Fix(rr, R), Fix(c - 1, C)); } } } return 0; }