제출 #827662

#제출 시각아이디문제언어결과실행 시간메모리
827662null_aweMaze (JOI23_ho_t3)C++14
43 / 100
2081 ms678612 KiB
#include <bits/stdc++.h> using namespace std; #define pii pair<int, int> const int UNTIL = 69420; vector<int> dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1}; int LG2[UNTIL]; void init() { LG2[1] = 0; for (int i = 2; i < UNTIL; ++i) LG2[i] = LG2[i >> 1] + 1; } class vEB { int u; int min; int max; vEB *summary; std::vector<vEB *> children; int high(int k){ int x = std::ceil(std::sqrt(u)); return std::floor(k / x); } int low(int k){ int x = std::ceil(std::sqrt(u)); return k % x; } int index(int k, int kk){ return (k * (int)std::sqrt(u)) + kk; } public: vEB(int U){ // u = std::pow(std::sqrt(U), 2); u = U; min = U; max = -1; if (u <= 2){ summary = nullptr; children = std::vector<vEB *> (0, nullptr); } else{ int children_count = std::ceil(std::sqrt(u)); int children_size = std::ceil(u / std::sqrt(u)); summary = new vEB(children_count); children = std::vector<vEB *> (children_count, nullptr); for(int i = 0; i < children_count; ++i){ children[i] = new vEB(children_count); } } } void insert(int k){ if(min > max){ min = max = k; return; } if(k < min){ int temp; temp = min; min = k; k = temp; } if(k > max) max = k; if(u == 2){ max = k; return; } int i = high(k); int j = low(k); children[i]->insert(j); if(children[i]->max == children[i]->min) summary->insert(i); } void remove(int k){ if(min > max) return; if(min == max){ min = u; max = -1; return; } if(u == 2){ if(k == 1){ if(min == 1){ min = u; max = -1; } else if(min == 0) max = 0; } else if(max == 0){ min = u; max = -1; } else if(max == 1) min = 1; return; } if(k == min){ int i = summary->min; min = index(i, children[i]->min); return; } int i = high(k); int j = low(k); children[i]->remove(j); if(children[i]->min > children[i]->max){ summary->remove(i); } if(k == max){ if(summary->min > summary->max){ max = min; } else{ i = summary->min; max = index(i, children[i]->max); } } } int getMin(){ return min; } int getMax(){ return max; } int universe(){ return u; } int successor(int k){ if(k <= min) return min; else if(k > max) return u; int i = high(k); int j = low(k); if(j <= children[i]->max){ int res = children[i]->successor(j); if(res >= (u / (int)std::sqrt(u))) return u; return k - j + res; } else{ int res = children[summary->successor(i)]->min; if(res >= children[summary->min]->u) return u; return index(summary->successor(i), res); } } }; vEB* build_veb(int u) { vEB* root = new vEB(u); for (int i = 0; i < u; ++i) { root->insert(i); } return root; } struct Sustree2 { int n, m; vector<vEB*> has; Sustree2() {} Sustree2(int n, int m) : n(n), m(m), has(4 * n) {} void build(int t, int tl, int tr) { cout << "BUILD" << endl; has[t] = build_veb(m + 1); if (tl == tr) return; build(2 * t, tl, (tl + tr) / 2); build(2 * t + 1, (tl + tr) / 2 + 1, tr); cout << "BUILT" << endl; } void build() { build(1, 0, n - 1); } void upd(int t, int tl, int tr, int p, int py) { // cout << t << ' ' << tl << ' ' << tr << endl; // for (int num : has[t]) cout << num << ' '; // cout << endl; if (tl == tr) { has[t]->remove(py); return; } if (p <= m) upd(2 * t, tl, (tl + tr) / 2, p, py); else upd(2 * t + 1, (tl + tr) / 2 + 1, tr, p, py); if (has[2 * t]->successor(py) != py && has[2 * t + 1]->successor(py) != py) has[t]->remove(py); } void upd(int x, int y) { cout << "UPD " << x << ' ' << y << endl; // cout << "UPD " << x << ' ' << y << endl; upd(1, 0, n - 1, x, y); // cout << "DONE" << endl; } pii qry(int t, int tl, int tr, int l, int r, int lo, int hi) { l = max(l, tl), r = min(r, tr); if (l > r) return {-1, -1}; if (tl == l && tr == r) { int gr = has[t]->successor(lo); if (gr > hi) return {-1, -1}; cout << tl << ' ' << gr << endl; if (tl == tr) { return {tl, gr}; } } int m = (tl + tr) / 2; pii f = qry(2 * t, tl, m, l, r, lo, hi); if (f.first >= 0) return f; return qry(2 * t + 1, m + 1, tr, l, r, lo, hi); } pii qry(int x1, int y1, int x2, int y2) { cout << "QRY" << endl; return qry(1, 0, n - 1, max(x1, 0), min(x2, n - 1), max(y1, 0), min(y2, m - 1)); } }; struct Sustree { int n, m; vector<multiset<int>> has; vector<int> first; Sustree() {} Sustree(int n, int m) : n(n), m(m), has(4 * n), first(4 * n) {} void build(int t, int tl, int tr) { multiset<int> cur; for (int i = tl; i <= tr; ++i) for (int j = 0; j < m; ++j) cur.insert(j); cur.insert(m); has[t] = cur; if (tl == tr) return; build(2 * t, tl, (tl + tr) / 2); build(2 * t + 1, (tl + tr) / 2 + 1, tr); } void build() { // cout << "BUILD ,;"; build(1, 0, n - 1); // cout << "DONE" << endl; } void upd(int t, int tl, int tr, int p, int py) { // cout << t << ' ' << tl << ' ' << tr << endl; // for (int num : has[t]) cout << num << ' '; // cout << endl; has[t].erase(has[t].find(py)); if (tl == tr) return; int m = (tl + tr) / 2; if (p <= m) upd(2 * t, tl, m, p, py); else upd(2 * t + 1, m + 1, tr, p, py); } void upd(int x, int y) { // cout << "UPD " << x << ' ' << y << endl; upd(1, 0, n - 1, x, y); // cout << "DONE" << endl; } pii qry(int t, int tl, int tr, int l, int r, int lo, int hi) { l = max(l, tl), r = min(r, tr); if (l > r) return {-1, -1}; if (tl == l && tr == r) { int gr = *has[t].lower_bound(lo); if (gr > hi) return {-1, -1}; if (tl == tr) { return {tl, gr}; } int m = (tl + tr) / 2; if (*has[2 * t].lower_bound(lo) <= hi) return qry(2 * t, tl, m, l, r, lo, hi); return qry(2 * t + 1, m + 1, tr, l, r, lo, hi); } int m = (tl + tr) / 2; pii f = qry(2 * t, tl, m, l, r, lo, hi); if (f.first >= 0) return f; return qry(2 * t + 1, m + 1, tr, l, r, lo, hi); } pii qry(int x1, int y1, int x2, int y2) { return qry(1, 0, n - 1, max(x1, 0), min(x2, n - 1), max(y1, 0), min(y2, m - 1)); } }; struct Segtree { int n; vector<bool> on; Segtree() {} Segtree(int n) : n(n), on(4 * n, 1) {} void upd(int t, int tl, int tr, int p) { if (tl == tr) on[t] = false; else { int m = (tl + tr) / 2; if (p <= m) upd(2 * t, tl, m, p); else upd(2 * t + 1, m + 1, tr, p); on[t] = on[2 * t] | on[2 * t + 1]; } } int qry(int t, int tl, int tr, int l, int r) { l = max(l, tl), r = min(r, tr); if (l > r) return -1; if (tl == l && tr == r && !on[t]) return -1; if (tl == tr) { assert(on[t]); return tl; } int m = (tl + tr) / 2; int f = qry(2 * t, tl, m, l, r); if (f >= 0) return f; return qry(2 * t + 1, m + 1, tr, l, r); } }; struct Groups { int r, c; vector<Segtree> rs, cs; Groups() {} Groups(int r, int c) : r(r), c(c) { for (int i = 0; i < r; ++i) { Segtree tmp(c); rs.push_back(tmp); } for (int i = 0; i < c; ++i) { Segtree tmp(r); cs.push_back(tmp); } } void upd(int x, int y) { // cout << x << ' ' << y << endl; rs[x].upd(1, 0, c - 1, y); cs[y].upd(1, 0, r - 1, x); // cout << "done" << endl; } int qrow(int row, int l, int rr) { if (row < 0 || row >= r) return -1; return rs[row].qry(1, 0, c - 1, max(l, 0), min(rr, c - 1)); } int qcol(int col, int l, int rr) { if (col < 0 || col >= c) return -1; return cs[col].qry(1, 0, r - 1, max(l, 0), min(rr, r - 1)); } }; int main() { init(); ios_base::sync_with_stdio(false); cin.tie(NULL); int r, c, n; cin >> r >> c >> n; int sx, sy; cin >> sx >> sy; --sx, --sy; int gx, gy; cin >> gx >> gy; --gx, --gy; vector<string> arr(r); for (int i = 0; i < r; ++i) cin >> arr[i]; // . = empty // # = wall Sustree sus(r, c); sus.build(); Groups groups(r, c); vector<vector<int>> dists(r, vector<int>(c, INT_MAX)); dists[sx][sy] = 0; // cout << dists[gx][gy] << '\n'; groups.upd(sx, sy); sus.upd(sx, sy); // cout << groups.qrow(sx, sy, sy) << endl; vector<pii> q; q.push_back({sx, sy}); queue<pii> rq; for (pii _p : q) rq.push(_p); while (rq.size()) { pii front = rq.front(); rq.pop(); int xx = front.first, yy = front.second; for (int d = 0; d < 4; ++d) { int nx = xx + dx[d], ny = yy + dy[d]; if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue; if (dists[nx][ny] < INT_MAX || arr[nx][ny] == '#') continue; rq.push({nx, ny}); q.push_back({nx, ny}); dists[nx][ny] = dists[xx][yy]; groups.upd(nx, ny); sus.upd(nx, ny); } } while (q.size()) { // for (int i = 0; i < r; ++i) { // for (int j = 0; j < c; ++j) cout << dists[i][j] << ' '; // cout << endl; // } // break; // cout << "here" << endl; // break; vector<pii> nq; for (pii p : q) { int x = p.first, y = p.second; // cout << x << ' ' << y << '\n'; if (x > 0 && dists[x - 1][y] <= dists[x][y]) { // cout << "t1" << endl; // query down: int cur; while ((cur = groups.qrow(x + n, y - n + 1, y + n - 1)) != -1) { nq.push_back({x + n, cur}); dists[x + n][cur] = dists[x][y] + 1; groups.upd(x + n, cur); sus.upd(x + n, cur); } if (x + n - 1 < r && y - n >= 0 && dists[x + n - 1][y - n] == INT_MAX) { nq.push_back({x + n - 1, y - n}); dists[x + n - 1][y - n] = dists[x][y] + 1; groups.upd(x + n - 1, y - n); sus.upd(x + n - 1, y - n); } if (x + n - 1 < r && y + n < c && dists[x + n - 1][y + n] == INT_MAX) { nq.push_back({x + n - 1, y + n}); dists[x + n - 1][y + n] = dists[x][y] + 1; groups.upd(x + n - 1, y + n); sus.upd(x + n - 1, y + n); } } else if (y < r - 1 && dists[x][y + 1] <= dists[x][y]) { // cout << "t4" << endl; // query left: int cur; while ((cur = groups.qcol(y - n, x - n + 1, x + n - 1)) != -1) { nq.push_back({cur, y - n}); dists[cur][y - n] = dists[x][y] + 1; groups.upd(cur, y - n); sus.upd(cur, y - n); } if (y - n + 1 >= 0 && x - n >= 0 && dists[x - n][y - n + 1] == INT_MAX) { nq.push_back({x - n, y - n + 1}); dists[x - n][y - n + 1] = dists[x][y] + 1; groups.upd(x - n, y - n + 1); sus.upd(x - n, y - n + 1); } if (y - n + 1 >= 0 && x + n < r && dists[x + n][y - n + 1] == INT_MAX) { nq.push_back({x + n, y - n + 1}); dists[x + n][y - n + 1] = dists[x][y] + 1; groups.upd(x + n, y - n + 1); sus.upd(x + n, y - n + 1); } } else { // query all: for (int i = -n; i <= n; i += 2 * n) { int cx = x + i, cyl = y - n + 1, cyr = y + n - 1, cur; while ((cur = groups.qrow(cx, cyl, cyr)) != -1) { nq.push_back({cx, cur}); dists[cx][cur] = dists[x][y] + 1; groups.upd(cx, cur); sus.upd(cx, cur); } } pii cur; while ((cur = sus.qry(x - n + 1, y - n, x + n - 1, y + n)).first != -1) { int nx = cur.first, ny = cur.second; nq.push_back({nx, ny}); dists[nx][ny] = dists[x][y] + 1; groups.upd(nx, ny); sus.upd(nx, ny); } } } queue<pii> rq; for (pii _p : nq) rq.push(_p); while (rq.size()) { pii front = rq.front(); rq.pop(); int xx = front.first, yy = front.second; for (int d = 0; d < 4; ++d) { int nx = xx + dx[d], ny = yy + dy[d]; if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue; if (dists[nx][ny] < INT_MAX || arr[nx][ny] == '#') continue; rq.push({nx, ny}); nq.push_back({nx, ny}); dists[nx][ny] = dists[xx][yy]; groups.upd(nx, ny); sus.upd(nx, ny); } } q = nq; } cout << dists[gx][gy] << '\n'; return 0; }

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In constructor 'vEB::vEB(int)':
Main.cpp:53:17: warning: unused variable 'children_size' [-Wunused-variable]
   53 |             int children_size = std::ceil(u / std::sqrt(u));
      |                 ^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...