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 "rect.h"
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> A;
int N, M;
struct seg {
vector<vector<int16_t>> sparse;
bool minmax;
int neut;
int op(int a, int b) {
if (minmax) return max(a,b);
return min(a,b);
}
int query(int ql, int qr) {
int len = qr-ql;
int x = 1;
int cnt = 0;
while (x*2 <= len) {x*=2; cnt++;}
return op(sparse[cnt][ql],sparse[cnt][qr-x+1]);
}
void init(int n, vector<int> a, bool type) {
minmax = type;
if (type) neut = -1e9;
else neut = 1e9;
sparse.assign(15, vector<int16_t>(n, neut));
for (int i = 0; i<n; i++) sparse[0][i] = a[i];
for (int i = 1; i<15; i++) {
for (int j = 0; j<n-(1<<(i-1)); j++) {
sparse[i][j] = op(sparse[i-1][j], sparse[i-1][j+(1<<(i-1))]);
}
}
}
};
vector<vector<array<int, 4>>> howFar; // 1,0; 0,1; -1,0; 0,-1;
void makeHowFar() {
howFar.assign(N, vector<array<int, 4>>(M));
for (int i = 0; i<N; i++) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> s;
for (int j = 0; j<M; j++) {
while (s.size() && s.top().first <= A[i][j]) {
howFar[i][s.top().second][1] = j;
s.pop();
}
s.push(pair<int, int>{A[i][j], j});
}
while (s.size()) {
auto aa = s.top();
s.pop();
howFar[i][aa.second][1] = M-1;
}
}
for (int i = 0; i<M; i++) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> s;
for (int j = 0; j<N; j++) {
while (s.size() && s.top().first <= A[j][i]) {
howFar[s.top().second][i][0] = j;
s.pop();
}
s.push(pair<int, int>{A[j][i], j});
}
while (s.size()) {
auto aa = s.top();
s.pop();
howFar[aa.second][i][0] = N-1;
}
}
for (int i = 0; i<N; i++) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> s;
for (int j = M-1; j>=0; j--) {
while (s.size() && s.top().first <= A[i][j]) {
howFar[i][s.top().second][3] = j;
s.pop();
}
s.push(pair<int, int>{A[i][j], j});
}
while (s.size()) {
auto aa = s.top();
s.pop();
howFar[i][aa.second][3] = 0;
}
}
for (int i = 0; i<M; i++) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> s;
for (int j = N-1; j>=0; j--) {
while (s.size() && s.top().first <= A[j][i]) {
howFar[s.top().second][i][2] = j;
s.pop();
}
s.push(pair<int, int>{A[j][i], j});
}
while (s.size()) {
auto aa = s.top();
s.pop();
howFar[aa.second][i][2] = 0;
}
}
}
vector<seg> howFar10, howFar01, howFar_10, howFar0_1;
void makeHowFarSegs() {
howFar10.resize(N);
for (int i = 0; i<N; i++) {
vector<int> a(M);
for (int j = 0; j<M; j++) a[j] = howFar[i][j][0];
howFar10[i].init(M, a, 0);
}
howFar01.resize(M);
for (int i = 0; i<M; i++) {
vector<int> a(N);
for (int j = 0; j<N; j++) a[j] = howFar[j][i][1];
howFar01[i].init(N, a, 0);
}
howFar_10.resize(N);
for (int i = 0; i<N; i++) {
vector<int> a(M);
for (int j = 0; j<M; j++) a[j] = howFar[i][j][2];
howFar_10[i].init(M, a, 1);
}
howFar0_1.resize(M);
for (int i = 0; i<M; i++) {
vector<int> a(N);
for (int j = 0; j<N; j++) a[j] = howFar[j][i][3];
howFar0_1[i].init(N, a, 1);
}
}
unordered_map<int64_t, bool> vis;
bool verify(int top, int bottom, int left, int right) { // top, bottom, left, right
if (bottom-top < 2) return 0;
if (right-left < 2) return 0;
if(!(howFar10[top].query(left+1, right-1) >= bottom)) return 0;
if(!(howFar_10[bottom].query(left+1, right-1) <= top)) return 0;
if(!(howFar01[left].query(top+1, bottom-1) >= right)) return 0;
if(!(howFar0_1[right].query(top+1, bottom-1) <= left)) return 0;
if (vis[(int64_t) top + (int64_t) bottom*2500 + (int64_t) left*2500*2500 + (int64_t) right*2500*2500*2500]) return 0;
vis[(int64_t) top + (int64_t) bottom*2500 + (int64_t) left*2500*2500 + (int64_t) right*2500*2500*2500] = 1;
return 1;
}
vector<array<int,4>> candidates;
void makeCandidates() {
candidates.resize((N-1)*(M-1)*8);
int cnt = 0;
for (int i = 1; i<N-1; i++) {
for (int j = 1; j<M-1; j++) {
int left = howFar[i][j+1][3], right = howFar[i][j-1][1];
int top = howFar[i+1][j][2], bottom = howFar[i-1][j][0];
int leftTop = howFar[i+1][left+1][2], leftBottom = howFar[i-1][left+1][0];
int rightTop = howFar[i+1][right-1][2], rightBottom = howFar[i-1][right-1][0];
candidates[cnt] = {top, i+1, left, j+1}; cnt++;
candidates[cnt] = {leftTop, i+1, left, j+1}; cnt++;
candidates[cnt] = {top, i+1, j-1, right}; cnt++;
candidates[cnt] = {rightTop, i+1, j-1, right}; cnt++;
candidates[cnt] = {i-1, bottom, left, j+1}; cnt++;
candidates[cnt] = {i-1, leftBottom, left, j+1}; cnt++;
candidates[cnt] = {i-1, bottom, j-1, right}; cnt++;
candidates[cnt] = {i-1, rightBottom, j-1, right}; cnt++;
}
}
}
long long count_rectangles(std::vector<std::vector<int> > _a) {
cerr << "start\n";
A = _a;
N = A.size();
M = A[0].size();
makeHowFar();
cerr << "madehowfar\n";
makeHowFarSegs();
cerr << "madesegs\n";
int res = 0;
makeCandidates();
cerr << "madecands\n";
vis.clear();
// sort(candidates.begin(), candidates.end());
cerr << "sorted\n";
// candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());
cerr << "sortedanderased\n";
for (auto i: candidates) {
res += verify(i[0], i[1], i[2], i[3]);
}
return res;
}
# | 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... |