結果
問題 | No.2786 RMQ on Grid Path |
ユーザー | 👑 seekworser |
提出日時 | 2024-06-13 21:21:52 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 9,471 bytes |
コンパイル時間 | 3,648 ms |
コンパイル使用メモリ | 277,444 KB |
実行使用メモリ | 31,612 KB |
最終ジャッジ日時 | 2024-06-14 20:53:44 |
合計ジャッジ時間 | 12,281 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | WA | - |
testcase_02 | WA | - |
testcase_03 | WA | - |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | WA | - |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | TLE | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
testcase_28 | -- | - |
testcase_29 | -- | - |
testcase_30 | -- | - |
testcase_31 | -- | - |
testcase_32 | -- | - |
testcase_33 | -- | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
ソースコード
//line 1 "answer.cpp" #include <bits/stdc++.h> //line 5 "/home/seekworser/.cpp_lib/competitive_library/atcoder/dsu.hpp" namespace atcoder { // Implement (union by size) + (path compression) // Reference: // Zvi Galil and Giuseppe F. Italiano, // Data structures and algorithms for disjoint set union problems struct dsu { public: dsu() : _n(0) {} explicit dsu(int n) : _n(n), parent_or_size(n, -1) {} int merge(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); int x = leader(a), y = leader(b); if (x == y) return x; if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y); parent_or_size[x] += parent_or_size[y]; parent_or_size[y] = x; return x; } bool same(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); return leader(a) == leader(b); } int leader(int a) { assert(0 <= a && a < _n); if (parent_or_size[a] < 0) return a; return parent_or_size[a] = leader(parent_or_size[a]); } int size(int a) { assert(0 <= a && a < _n); return -parent_or_size[leader(a)]; } std::vector<std::vector<int>> groups() { std::vector<int> leader_buf(_n), group_size(_n); for (int i = 0; i < _n; i++) { leader_buf[i] = leader(i); group_size[leader_buf[i]]++; } std::vector<std::vector<int>> result(_n); for (int i = 0; i < _n; i++) { result[i].reserve(group_size[i]); } for (int i = 0; i < _n; i++) { result[leader_buf[i]].push_back(i); } result.erase( std::remove_if(result.begin(), result.end(), [&](const std::vector<int>& v) { return v.empty(); }), result.end()); return result; } private: int _n; // root node: -1 * component size // otherwise: parent std::vector<int> parent_or_size; }; } // namespace atcoder //line 5 "/home/seekworser/.cpp_lib/competitive_library/atcoder/segtree.hpp" //line 2 "/home/seekworser/.cpp_lib/competitive_library/atcoder/internal_bit.hpp" #ifdef _MSC_VER #include <intrin.h> #endif namespace atcoder { namespace internal { // @param n `0 <= n` // @return minimum non-negative `x` s.t. `n <= 2**x` int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } // @param n `1 <= n` // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0` constexpr int bsf_constexpr(unsigned int n) { int x = 0; while (!(n & (1 << x))) x++; return x; } // @param n `1 <= n` // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0` int bsf(unsigned int n) { #ifdef _MSC_VER unsigned long index; _BitScanForward(&index, n); return index; #else return __builtin_ctz(n); #endif } } // namespace internal } // namespace atcoder //line 7 "/home/seekworser/.cpp_lib/competitive_library/atcoder/segtree.hpp" namespace atcoder { template <class S, S (*_op)(S, S), S (*_e)()> struct segtree { public: S (*op)(S, S) = _op; S (*e)() = _e; segtree() : segtree(0) {} explicit segtree(const std::vector<S>& v) : _n(int(v.size())) { log = internal::ceil_pow2(_n); size = 1 << log; d = std::vector<S>(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } explicit segtree(int n) : segtree(std::vector<S>(n, _e())) {} void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } void add(int p, S x) { assert(0 <= p && p < _n); (*this).set(p, (*this).get(p) + x); } S get(int p) const { assert(0 <= p && p < _n); return d[p + size]; } S prod(int l, int r) const { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() const { return d[1]; } template <bool (*f)(S)> int max_right(int l) const { return max_right(l, [](S x) { return f(x); }); } template <class F> int max_right(int l, F f) const { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template <bool (*f)(S)> int min_left(int r) const { return min_left(r, [](S x) { return f(x); }); } template <class F> int min_left(int r, F f) const { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } int n() const {return (*this)._n;} private: int _n, size, log; std::vector<S> d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; } // namespace atcoder //line 4 "answer.cpp" using namespace std; // using ll = long long; const int INF = 1 << 30; const vector<pair<int,int>> dxy = {{0,1},{0,-1},{1,0},{-1,0}}; int op_min(int a, int b) { return min(a, b); } int e_min() { return INF; } int op_max(int a, int b) { return max(a, b); } int e_max() { return -INF; } vector<int> order; vector<int> depth; vector<int> visited; void eulertour(const vector<vector<int>> &g) { int n = g.size(); visited = vector<int>(n, 2*n); auto dfs = [&](auto self, int u, int d, int parent) -> void { if (visited[u] == 2*n) visited[u] = order.size(); order.push_back(u); depth.push_back(d); for (int v : g[u]) if (v != parent) self(self, v, d+1, u); order.push_back(u); depth.push_back(d); }; dfs(dfs, 0, 0, -1); return; } int main() { int h,w; cin >> h >> w; vector a(h, vector<int>(w)); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { cin >> a[i][j]; } } vector<pair<int,int>> pos; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { pos.push_back({i,j}); } } sort(pos.begin(), pos.end(), [a](pair<int,int> p, pair<int,int> q) { return a[p.first][p.second] < a[q.first][q.second]; }); vector<vector<int>> g = [&]() { atcoder::dsu uf(h*w); vector<vector<int>> g(h*w); for (auto [i, j] : pos) { cout << i << " " << j << endl; for (auto [dx, dy] : dxy) { if (i+dx < 0 || i+dx >= h || j+dy < 0 || j+dy >= w) continue; int u = i*w+j; int v = (i+dx)*w+(j+dy); if (!uf.same(u, v)) { uf.merge(u, v); g[u].push_back(v); g[v].push_back(u); } } } return g; }(); eulertour(g); atcoder::segtree<int, op_min, e_min> seg_depth(depth); auto lca = [&](int u, int v) -> int { if (visited[u] > visited[v]) swap(u, v); int min_depth = seg_depth.prod(visited[u], visited[v]+1); int lca_pos = seg_depth.max_right(visited[u], [&](int x) -> bool { return x > min_depth;}); return order[lca_pos]; }; int q; cin >> q; vector<vector<tuple<int,int>>> query(2*h*w); for (int i = 0; i < q; i++) { int rs, cs, rt, ct; cin >> rs >> cs >> rt >> ct; int u = (rs-1)*w+(cs-1); int v = (rt-1)*w+(ct-1); int l = lca(u, v); cout << u << " " << v << " " << l << endl; query[u].push_back({depth[visited[l]], i}); query[v].push_back({depth[visited[l]], i}); } atcoder::segtree<int, op_max, e_max> seg_query(h*w); vector<int> ans (q, INF); auto dfs = [&] (auto self, int u, int parent, int parent_val) -> void { int val = a[u/w][u%w]; seg_query.set(depth[visited[u]], min(val, parent_val)); cout << u << endl; for (int i = 0; i < h*w; i++) cout << seg_query.get(i) << " "; cout << endl; for (auto [d, id] : query[u]) { cout << d << " " << id << endl; ans[id] = min(ans[id], seg_query.prod(d+1, h*w)); } for (auto v : g[u]) if (v != parent) self(self, v, u, val); seg_query.set(depth[visited[u]], -INF); }; dfs(dfs, 0, -1, INF); for (auto x : ans) cout << x << '\n'; }