// Judges with GCC >= 12 only needs Ofast // #pragma GCC optimize("O3,no-stack-protector,fast-math,unroll-loops,tree-vectorize") // MLE optimization // #pragma GCC optimize("conserve-stack") // Old judges // #pragma GCC target("sse4.2,popcnt,lzcnt,abm,mmx,fma,bmi,bmi2") // New judges. Test with assert(__builtin_cpu_supports("avx2")); // #pragma GCC target("avx2,popcnt,lzcnt,abm,bmi,bmi2,fma,tune=native") // Atcoder // #pragma GCC target("avx2,popcnt,lzcnt,abm,bmi,bmi2,fma") /* #include #include using namespace __gnu_pbds; typedef tree,rb_tree_tag,tree_order_statistics_node_update> ods; - insert(x),erase(x) - find_by_order(k): return iterator to the k-th smallest element - order_of_key(x): the number of elements that are strictly smaller */ #include using namespace std; using ld = long double; using ll = long long; using u32 = unsigned int; using u64 = unsigned long long; using i128 = __int128; using u128 = unsigned __int128; using f128 = __float128; #define pii pair #define pll pair #define all(x) (x).begin(),(x).end() #define rall(x) (x).rbegin(),(x).rend() #define ars(x) (x),(x+n) #define TIME (1.0 * clock() / CLOCKS_PER_SEC) #define For(i,a,b) for (int i=(a); i<(b); i++) #define rep(i,a) For(i,0,a) #define rev(i,a,b) for (int i=(a); i>(b); i--) #define FOR(i,a,b) for (int i=(a); i<=(b); i++) #define REP(i,a) FOR(i,1,a) #define REV(i,a,b) for (int i=(a); i>=(b); i--) #define pb push_back #define eb emplace_back #define sz(x) ((int)(x).size()) #define mp make_pair #define fi first #define se second #define FT ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); using vi=vector; using vll = vector; template using vc = vector; template using vvc = vector>; template using vvvc = vector>; template using vvvvc = vector>; template using vvvvvc = vector>; template using pq = priority_queue; template using pqg = priority_queue, greater>; #define vv(type, name, h, ...) \ vector> name(h, vector(__VA_ARGS__)) #define vvv(type, name, h, w, ...) \ vector>> name( \ h, vector>(w, vector(__VA_ARGS__))) #define vvvv(type, name, a, b, c, ...) \ vector>>> name( \ a, vector>>( \ b, vector>(c, vector(__VA_ARGS__)))) //template //using ods = // tree, rb_tree_tag, tree_order_statistics_node_update>; #define MIN(v) *min_element(all(v)) #define MAX(v) *max_element(all(v)) #define LB(c, x) distance((c).begin(), lower_bound(all(c), (x))) #define UB(c, x) distance((c).begin(), upper_bound(all(c), (x))) #define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit() template bool chkmin(T &x,T y){return x>y?x=y,1:0;} template bool chkmax(T &x,T y){return x using pq = priority_queue; template using pqg = priority_queue, greater>; void __print(int x) {cerr << x;} void __print(long x) {cerr << x;} void __print(long long x) {cerr << x;} void __print(unsigned x) {cerr << x;} void __print(unsigned long x) {cerr << x;} void __print(unsigned long long x) {cerr << x;} void __print(float x) {cerr << x;} void __print(double x) {cerr << x;} void __print(long double x) {cerr << x;} void __print(char x) {cerr << '\'' << x << '\'';} void __print(const char *x) {cerr << '\"' << x << '\"';} void __print(const string &x) {cerr << '\"' << x << '\"';} void __print(bool x) {cerr << (x ? "true" : "false");} template void __print(const pair &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';} template void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";} void _print() {cerr << "]\n";} template void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);} void dbg_out() { cerr << endl; } template void dbg_out(Head H, Tail... T) { __print(H); if (sizeof...(T)) cerr << ", "; dbg_out(T...); } #define dbg(...) cerr << "[" << #__VA_ARGS__ << "]:"; dbg_out(__VA_ARGS__); //---------------for faster io----------------------------------- #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace yosupo { namespace internal { template using is_signed_int128 = typename std::conditional::value || std::is_same::value, std::true_type, std::false_type>::type; template using is_unsigned_int128 = typename std::conditional::value || std::is_same::value, std::true_type, std::false_type>::type; template using make_unsigned_int128 = typename std::conditional::value, __uint128_t, unsigned __int128>; template using is_integral = typename std::conditional::value || internal::is_signed_int128::value || internal::is_unsigned_int128::value, std::true_type, std::false_type>::type; template using is_signed_int = typename std::conditional<(is_integral::value && std::is_signed::value) || is_signed_int128::value, std::true_type, std::false_type>::type; template using is_unsigned_int = typename std::conditional<(is_integral::value && std::is_unsigned::value) || is_unsigned_int128::value, std::true_type, std::false_type>::type; template using to_unsigned = typename std::conditional< is_signed_int128::value, make_unsigned_int128, typename std::conditional::value, std::make_unsigned, std::common_type>::type>::type; template using is_integral_t = std::enable_if_t::value>; template using is_signed_int_t = std::enable_if_t::value>; template using is_unsigned_int_t = std::enable_if_t::value>; template using to_unsigned_t = typename to_unsigned::type; } // namespace internal } // namespace yosupo namespace yosupo { struct Scanner { public: Scanner(const Scanner&) = delete; Scanner& operator=(const Scanner&) = delete; Scanner(FILE* fp) : fd(fileno(fp)) { line[0] = 127; } void read() {} template void read(H& h, T&... t) { bool f = read_single(h); assert(f); read(t...); } int read_unsafe() { return 0; } template int read_unsafe(H& h, T&... t) { bool f = read_single(h); if (!f) return 0; return 1 + read_unsafe(t...); } int close() { return ::close(fd); } private: static constexpr int SIZE = 1 << 15; int fd = -1; std::array line; int st = 0, ed = 0; bool eof = false; bool read_single(std::string& ref) { if (!skip_space()) return false; ref = ""; while (true) { char c = top(); if (c <= ' ') break; ref += c; st++; } return true; } bool read_single(double& ref) { std::string s; if (!read_single(s)) return false; ref = std::stod(s); return true; } template ::value>* = nullptr> bool read_single(T& ref) { if (!skip_space<50>()) return false; ref = top(); st++; return true; } template * = nullptr, std::enable_if_t::value>* = nullptr> bool read_single(T& sref) { using U = internal::to_unsigned_t; if (!skip_space<50>()) return false; bool neg = false; if (line[st] == '-') { neg = true; st++; } U ref = 0; do { ref = 10 * ref + (line[st++] & 0x0f); } while (line[st] >= '0'); sref = neg ? -ref : ref; return true; } template * = nullptr, std::enable_if_t::value>* = nullptr> bool read_single(U& ref) { if (!skip_space<50>()) return false; ref = 0; do { ref = 10 * ref + (line[st++] & 0x0f); } while (line[st] >= '0'); return true; } bool reread() { if (ed - st >= 50) return true; if (st > SIZE / 2) { std::memmove(line.data(), line.data() + st, ed - st); ed -= st; st = 0; } if (eof) return false; auto u = ::read(fd, line.data() + ed, SIZE - ed); if (u == 0) { eof = true; line[ed] = '\0'; u = 1; } ed += int(u); line[ed] = char(127); return true; } char top() { if (st == ed) { bool f = reread(); assert(f); } return line[st]; } template bool skip_space() { while (true) { while (line[st] <= ' ') st++; if (ed - st > TOKEN_LEN) return true; if (st > ed) st = ed; for (auto i = st; i < ed; i++) { if (line[i] <= ' ') return true; } if (!reread()) return false; } } }; struct Printer { public: template void write() {} template void write(const H& h, const T&... t) { if (F) write_single(sep); write_single(h); write(t...); } template void writeln(const T&... t) { write(t...); write_single('\n'); } Printer(FILE* _fp) : fd(fileno(_fp)) {} ~Printer() { flush(); } int close() { flush(); return ::close(fd); } void flush() { if (pos) { auto res = ::write(fd, line.data(), pos); assert(res != -1); pos = 0; } } private: static std::array, 100> small; static std::array tens; static constexpr size_t SIZE = 1 << 15; int fd; std::array line; size_t pos = 0; std::stringstream ss; template ::value>* = nullptr> void write_single(const T& val) { if (pos == SIZE) flush(); line[pos++] = val; } template * = nullptr, std::enable_if_t::value>* = nullptr> void write_single(const T& val) { using U = internal::to_unsigned_t; if (val == 0) { write_single('0'); return; } if (pos > SIZE - 50) flush(); U uval = val; if (val < 0) { write_single('-'); uval = -uval; } write_unsigned(uval); } template * = nullptr> void write_single(U uval) { if (uval == 0) { write_single('0'); return; } if (pos > SIZE - 50) flush(); write_unsigned(uval); } static int calc_len(uint64_t x) { int i = ((63 - std::countl_zero(x)) * 3 + 3) / 10; if (x < tens[i]) return i; else return i + 1; } template * = nullptr, std::enable_if_t<2 >= sizeof(U)>* = nullptr> void write_unsigned(U uval) { size_t len = calc_len(uval); pos += len; char* ptr = line.data() + pos; while (uval >= 100) { ptr -= 2; memcpy(ptr, small[uval % 100].data(), 2); uval /= 100; } if (uval >= 10) { memcpy(ptr - 2, small[uval].data(), 2); } else { *(ptr - 1) = char('0' + uval); } } template * = nullptr, std::enable_if_t<4 == sizeof(U)>* = nullptr> void write_unsigned(U uval) { std::array buf; memcpy(buf.data() + 6, small[uval % 100].data(), 2); memcpy(buf.data() + 4, small[uval / 100 % 100].data(), 2); memcpy(buf.data() + 2, small[uval / 10000 % 100].data(), 2); memcpy(buf.data() + 0, small[uval / 1000000 % 100].data(), 2); if (uval >= 100000000) { if (uval >= 1000000000) { memcpy(line.data() + pos, small[uval / 100000000 % 100].data(), 2); pos += 2; } else { line[pos] = char('0' + uval / 100000000); pos++; } memcpy(line.data() + pos, buf.data(), 8); pos += 8; } else { size_t len = calc_len(uval); memcpy(line.data() + pos, buf.data() + (8 - len), len); pos += len; } } template * = nullptr, std::enable_if_t<8 == sizeof(U)>* = nullptr> void write_unsigned(U uval) { size_t len = calc_len(uval); pos += len; char* ptr = line.data() + pos; while (uval >= 100) { ptr -= 2; memcpy(ptr, small[uval % 100].data(), 2); uval /= 100; } if (uval >= 10) { memcpy(ptr - 2, small[uval].data(), 2); } else { *(ptr - 1) = char('0' + uval); } } template < class U, std::enable_if_t::value>* = nullptr> void write_unsigned(U uval) { static std::array buf; size_t len = 0; while (uval > 0) { buf[len++] = char((uval % 10) + '0'); uval /= 10; } std::reverse(buf.begin(), buf.begin() + len); memcpy(line.data() + pos, buf.data(), len); pos += len; } void write_single(const std::string& s) { for (char c : s) write_single(c); } void write_single(const char* s) { size_t len = strlen(s); for (size_t i = 0; i < len; i++) write_single(s[i]); } template void write_single(const std::vector& val) { auto n = val.size(); for (size_t i = 0; i < n; i++) { if (i) write_single(' '); write_single(val[i]); } } }; std::array, 100> Printer::small = [] { std::array, 100> table; for (int i = 0; i <= 99; i++) { table[i][1] = char('0' + (i % 10)); table[i][0] = char('0' + (i / 10 % 10)); } return table; }(); std::array Printer::tens = [] { std::array table; for (int i = 0; i < 20; i++) { table[i] = 1; for (int j = 0; j < i; j++) { table[i] *= 10; } } return table; }(); } // namespace yosupo //sc.read(type) to enter input //sc.write(type) to print out answer //sc.writeln() to go break the line using namespace yosupo; Scanner sc(stdin); Printer pr(stdout); const int INF=1e9; const ll INFI=1e15; //----------Author: Nguyen Ho Nam,UIT, Saigon----------------- const int MAX = 505; int H, W, Q; int grid[MAX][MAX]; int dist[MAX][MAX]; bool vis[MAX][MAX]; int dx[] = {-1, 1, 0, 0}; int dy[] = {0, 0, -1, 1}; int bfs(int rs, int cs, int rt, int ct) { for (int i = 0; i < H; ++i) { fill(dist[i], dist[i] + W, INT_MAX); fill(vis[i], vis[i] + W, false); } priority_queue>, vector>>, greater<>> pq; pq.push({grid[rs][cs], {rs, cs}}); dist[rs][cs] = grid[rs][cs]; while (!pq.empty()) { auto [cost, pos] = pq.top(); pq.pop(); int x = pos.first; int y = pos.second; if (vis[x][y]) continue; vis[x][y] = true; for (int d = 0; d < 4; ++d) { int nx = x + dx[d]; int ny = y + dy[d]; if (nx >= 0 && nx < H && ny >= 0 && ny < W) { int new_cost = max(cost, grid[nx][ny]); if (new_cost < dist[nx][ny]) { dist[nx][ny] = new_cost; pq.push({new_cost, {nx, ny}}); } } } } return dist[rt][ct]; } void solve() { sc.read(H,W); rep(i,H) rep(j,W){ sc.read(grid[i][j]); } sc.read(Q); while(Q--){ int rs,cs,rt,ct; sc.read(rs,cs,rt,ct); rs--; cs--; rt--; ct--; pr.writeln(bfs(rs,cs,rt,ct)); } } int main(){ FT; int t=1; //sc.read(t); int tc=0; while(t--) { //tc++; //cout << "Case #" << tc << ": "; solve(); // cerr << "Time elapsed: " << TIME << " s.\n"; } }