#include <bits/stdc++.h> using namespace std; const int CYCLE = 8 * 7 * 3 * 5; const int LOG = 15; int main() { // ios_base::sync_with_stdio(false); // cin.tie(nullptr); int n, m, q; // cin >> n >> m >> q; scanf("%d%d%d", &n, &m, &q); vector<vector<string>> s(n, vector<string>(m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j){ char buf[20]; scanf("%s", buf); s[i][j] = string(buf); // cin >> s[i][j]; } } vector<bool> blocked_rows[CYCLE]; vector<bool> blocked_cols[CYCLE]; vector<int> next_row_u[CYCLE]; vector<int> next_row_d[CYCLE]; vector<int> next_col_l[CYCLE]; vector<int> next_col_r[CYCLE]; bool always_rows_blocked = true, always_cols_blocked = true; for (int t = 0; t < CYCLE; ++t) { blocked_rows[t].resize(n); blocked_cols[t].resize(m); next_row_u[t].resize(n + 1); next_row_d[t].resize(n + 1); next_col_l[t].resize(m + 1); next_col_r[t].resize(m + 1); bool a_row_blocked = false, a_col_blocked = false; for (int i = 0; i < n; ++i) { blocked_rows[t][i] = true; for (int j = 0; j < m; ++j) { if (s[i][j][t % s[i][j].length()] == '0') { blocked_rows[t][i] = false; break; } } if (blocked_rows[t][i]) a_row_blocked = true; } next_row_u[t][0] = 0; for (int i = 1; i <= n; ++i) next_row_u[t][i] = blocked_rows[t][i - 1] ? i : next_row_u[t][i - 1]; next_row_d[t][n] = n; for (int i = n - 1; i >= 0; --i) next_row_d[t][i] = blocked_rows[t][i] ? i : next_row_d[t][i + 1]; for (int j = 0; j < m; ++j) { blocked_cols[t][j] = true; for (int i = 0; i < n; ++i) { if (s[i][j][t % s[i][j].length()] == '1') { blocked_cols[t][j] = false; break; } } if (blocked_cols[t][j]) a_col_blocked = true; } next_col_l[t][0] = 0; for (int j = 1; j <= m; ++j) next_col_l[t][j] = blocked_cols[t][j - 1] ? j : next_col_l[t][j - 1]; next_col_r[t][m] = m; for (int j = m - 1; j >= 0; --j) next_col_r[t][j] = blocked_cols[t][j] ? j : next_col_r[t][j + 1]; assert(!(a_row_blocked && a_col_blocked)); if (!a_col_blocked) always_cols_blocked = false; if (!a_row_blocked) always_rows_blocked = false; } int N = -1; vector<int16_t> next[LOG][CYCLE], prev[LOG][CYCLE]; vector<int> nextzero[CYCLE], prevzero[CYCLE]; if (always_rows_blocked) { N = n; for (int t = 0; t < CYCLE; ++t) { nextzero[t] = next_row_d[t]; prevzero[t] = next_row_u[t]; } } if (always_cols_blocked) { N = m; for (int t = 0; t < CYCLE; ++t) { nextzero[t] = next_col_r[t]; prevzero[t] = next_col_l[t]; } } if (always_rows_blocked || always_cols_blocked) { for (int t = 0; t < CYCLE; ++t) { next[0][t].resize(N + 1); prev[0][t].resize(N + 1); for (int i = 0; i <= N; ++i) { next[0][t][i] = nextzero[(t + 1) % CYCLE][nextzero[t][i]]; prev[0][t][i] = prevzero[(t + 1) % CYCLE][prevzero[t][i]]; } } for (int l = 1; l < LOG; ++l) { for (int t = 0; t < CYCLE; ++t) { next[l][t].resize(N + 1); prev[l][t].resize(N + 1); int tplus = (t + (1 << (l - 1))) % CYCLE; for (int i = 0; i <= N; ++i) { next[l][t][i] = next[l-1][tplus][next[l - 1][t][i]]; prev[l][t][i] = prev[l-1][tplus][prev[l - 1][t][i]]; } } } } while (q--) { // if (q % 10000 == 0) // cerr << q << endl; int t, a, b, c, d; // cin >> t >> a >> b >> c >> d; scanf("%d%d%d%d%d", &t, &a, &b, &c, &d); const int original_t = t; int tt = t % CYCLE; if (a < c) a = min(c, next_row_d[tt][a]); if (a > c) a = max(c, next_row_u[tt][a]); if (b < d) b = min(d, next_col_r[tt][b]); if (b > d) b = max(d, next_col_l[tt][b]); if (always_cols_blocked) assert(a == c); if (always_rows_blocked) assert(b == d); if (always_cols_blocked || always_rows_blocked) { int beg, end; if (always_cols_blocked) { beg = b; end = d; } else { beg = a; end = c; } bool fwd = (beg < end); for (int l = LOG - 1; l >= 0;) { int target = (fwd ? next : prev)[l][t % CYCLE][beg]; if ((fwd && target < end) || (!fwd && target > end)) { t += (1 << l); beg = target; if (l < LOG - 1) --l; } else { --l; } } if (always_cols_blocked) b = beg; else a = beg; } tt = t % CYCLE; int iter = 0; if (true) { while (true) { ++iter; // const vector<bool>& blocked_row = blocked_rows[t % CYCLE]; // const vector<bool>& blocked_col = blocked_cols[t % CYCLE]; // while (a < c && !blocked_row[a]) ++a; // while (a > c && !blocked_row[a-1]) --a; // while (b < d && !blocked_col[b]) ++b; // while (b > d && !blocked_col[b-1]) --b; if (a < c) a = min(c, next_row_d[tt][a]); if (a > c) a = max(c, next_row_u[tt][a]); if (b < d) b = min(d, next_col_r[tt][b]); if (b > d) b = max(d, next_col_l[tt][b]); if (a == c && b == d) break; else { ++t; ++tt; if (tt == CYCLE) tt = 0; } } assert(iter < CYCLE + 10); // assert(t - original_t <= CYCLE + 10); } printf("%d\n", t); // cout << t << endl; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | #include <bits/stdc++.h> using namespace std; const int CYCLE = 8 * 7 * 3 * 5; const int LOG = 15; int main() { // ios_base::sync_with_stdio(false); // cin.tie(nullptr); int n, m, q; // cin >> n >> m >> q; scanf("%d%d%d", &n, &m, &q); vector<vector<string>> s(n, vector<string>(m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j){ char buf[20]; scanf("%s", buf); s[i][j] = string(buf); // cin >> s[i][j]; } } vector<bool> blocked_rows[CYCLE]; vector<bool> blocked_cols[CYCLE]; vector<int> next_row_u[CYCLE]; vector<int> next_row_d[CYCLE]; vector<int> next_col_l[CYCLE]; vector<int> next_col_r[CYCLE]; bool always_rows_blocked = true, always_cols_blocked = true; for (int t = 0; t < CYCLE; ++t) { blocked_rows[t].resize(n); blocked_cols[t].resize(m); next_row_u[t].resize(n + 1); next_row_d[t].resize(n + 1); next_col_l[t].resize(m + 1); next_col_r[t].resize(m + 1); bool a_row_blocked = false, a_col_blocked = false; for (int i = 0; i < n; ++i) { blocked_rows[t][i] = true; for (int j = 0; j < m; ++j) { if (s[i][j][t % s[i][j].length()] == '0') { blocked_rows[t][i] = false; break; } } if (blocked_rows[t][i]) a_row_blocked = true; } next_row_u[t][0] = 0; for (int i = 1; i <= n; ++i) next_row_u[t][i] = blocked_rows[t][i - 1] ? i : next_row_u[t][i - 1]; next_row_d[t][n] = n; for (int i = n - 1; i >= 0; --i) next_row_d[t][i] = blocked_rows[t][i] ? i : next_row_d[t][i + 1]; for (int j = 0; j < m; ++j) { blocked_cols[t][j] = true; for (int i = 0; i < n; ++i) { if (s[i][j][t % s[i][j].length()] == '1') { blocked_cols[t][j] = false; break; } } if (blocked_cols[t][j]) a_col_blocked = true; } next_col_l[t][0] = 0; for (int j = 1; j <= m; ++j) next_col_l[t][j] = blocked_cols[t][j - 1] ? j : next_col_l[t][j - 1]; next_col_r[t][m] = m; for (int j = m - 1; j >= 0; --j) next_col_r[t][j] = blocked_cols[t][j] ? j : next_col_r[t][j + 1]; assert(!(a_row_blocked && a_col_blocked)); if (!a_col_blocked) always_cols_blocked = false; if (!a_row_blocked) always_rows_blocked = false; } int N = -1; vector<int16_t> next[LOG][CYCLE], prev[LOG][CYCLE]; vector<int> nextzero[CYCLE], prevzero[CYCLE]; if (always_rows_blocked) { N = n; for (int t = 0; t < CYCLE; ++t) { nextzero[t] = next_row_d[t]; prevzero[t] = next_row_u[t]; } } if (always_cols_blocked) { N = m; for (int t = 0; t < CYCLE; ++t) { nextzero[t] = next_col_r[t]; prevzero[t] = next_col_l[t]; } } if (always_rows_blocked || always_cols_blocked) { for (int t = 0; t < CYCLE; ++t) { next[0][t].resize(N + 1); prev[0][t].resize(N + 1); for (int i = 0; i <= N; ++i) { next[0][t][i] = nextzero[(t + 1) % CYCLE][nextzero[t][i]]; prev[0][t][i] = prevzero[(t + 1) % CYCLE][prevzero[t][i]]; } } for (int l = 1; l < LOG; ++l) { for (int t = 0; t < CYCLE; ++t) { next[l][t].resize(N + 1); prev[l][t].resize(N + 1); int tplus = (t + (1 << (l - 1))) % CYCLE; for (int i = 0; i <= N; ++i) { next[l][t][i] = next[l-1][tplus][next[l - 1][t][i]]; prev[l][t][i] = prev[l-1][tplus][prev[l - 1][t][i]]; } } } } while (q--) { // if (q % 10000 == 0) // cerr << q << endl; int t, a, b, c, d; // cin >> t >> a >> b >> c >> d; scanf("%d%d%d%d%d", &t, &a, &b, &c, &d); const int original_t = t; int tt = t % CYCLE; if (a < c) a = min(c, next_row_d[tt][a]); if (a > c) a = max(c, next_row_u[tt][a]); if (b < d) b = min(d, next_col_r[tt][b]); if (b > d) b = max(d, next_col_l[tt][b]); if (always_cols_blocked) assert(a == c); if (always_rows_blocked) assert(b == d); if (always_cols_blocked || always_rows_blocked) { int beg, end; if (always_cols_blocked) { beg = b; end = d; } else { beg = a; end = c; } bool fwd = (beg < end); for (int l = LOG - 1; l >= 0;) { int target = (fwd ? next : prev)[l][t % CYCLE][beg]; if ((fwd && target < end) || (!fwd && target > end)) { t += (1 << l); beg = target; if (l < LOG - 1) --l; } else { --l; } } if (always_cols_blocked) b = beg; else a = beg; } tt = t % CYCLE; int iter = 0; if (true) { while (true) { ++iter; // const vector<bool>& blocked_row = blocked_rows[t % CYCLE]; // const vector<bool>& blocked_col = blocked_cols[t % CYCLE]; // while (a < c && !blocked_row[a]) ++a; // while (a > c && !blocked_row[a-1]) --a; // while (b < d && !blocked_col[b]) ++b; // while (b > d && !blocked_col[b-1]) --b; if (a < c) a = min(c, next_row_d[tt][a]); if (a > c) a = max(c, next_row_u[tt][a]); if (b < d) b = min(d, next_col_r[tt][b]); if (b > d) b = max(d, next_col_l[tt][b]); if (a == c && b == d) break; else { ++t; ++tt; if (tt == CYCLE) tt = 0; } } assert(iter < CYCLE + 10); // assert(t - original_t <= CYCLE + 10); } printf("%d\n", t); // cout << t << endl; } } |