This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |