제출 #535989

#제출 시각아이디문제언어결과실행 시간메모리
535989KoDRectangles (IOI19_rect)C++17
100 / 100
2143 ms322328 KiB
#include <bits/stdc++.h> #include "rect.h" using ll = long long; using namespace std; struct fenwick { vector<int> data; explicit fenwick(const int n) : data(n + 1) {} void add(int i, const int x) { for (i += 1; i < (int)data.size(); i += i & -i) data[i] += x; } int pref(int i) const { int ret = 0; for (; i > 0; i -= i & -i) ret += data[i]; return ret; } int fold(const int l, const int r) const { return pref(r) - pref(l); } }; template <class F> vector<pair<int, int>> enumerate(const int n, const F& f) { vector<pair<int, int>> valid; vector<int> stack; for (int i = 0; i < n; ++i) { int sofar = 0; const int r = f(i); while (!stack.empty()) { const int j = stack.back(); const int l = f(j); if (min(l, r) > sofar and i - j > 1) valid.emplace_back(j, i); if (l >= r) break; stack.pop_back(); sofar = max(sofar, l); } stack.push_back(i); } return valid; } ll count_rectangles(vector<vector<int>> a) { const int n = a.size(); const int m = a[0].size(); if (n <= 2 or m <= 2) return 0; vector fix_down(n, vector<vector<int>>(m)); for (int j = 0; j < m; ++j) { for (const auto& [u, d] : enumerate(n, [&](const int i) { return a[i][j]; })) { fix_down[d][j].push_back(u); } } vector<tuple<int, int, int>> lr; for (const auto& [l, r] : enumerate(m, [&](const int j) { return a[1][j]; })) { lr.emplace_back(l, r, 0); } vector valid_up(n, fenwick(m)); int count = 0; for (int down = 2; down < n; ++down) { for (int j = 0; j < m; ++j) { for (const int up : fix_down[down][j]) valid_up[up].add(j, 1); } for (const auto& [l, r, u] : lr) { for (const int up : fix_down[down][l + 1]) { if (up < u) break; if (valid_up[up].fold(l + 1, r) == r - l - 1) count += 1; } } if (down + 1 < n) { vector<tuple<int, int, int>> next; int idx = 0; for (const auto& [l, r] : enumerate(m, [&](const int j) { return a[down][j]; })) { bool done = false; while (idx < (int)lr.size()) { const auto& [l0, r0, u] = lr[idx]; if (l0 == l and r0 == r) { next.emplace_back(l, r, u); done = true; break; } if (r0 < r or (r0 == r and l0 > l)) { idx += 1; } else { break; } } if (!done) next.emplace_back(l, r, down - 1); } lr = std::move(next); for (int j = 0; j < m; ++j) { for (const int up : fix_down[down][j]) valid_up[up].add(j, -1); } } } return count; }
#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...