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;
#define sz(v) int(v.size())
#define ar array
typedef long long ll;
#ifdef LOCAL
const int N = 1e2;
#endif
#ifndef LOCAL
const int N = 2.5e3+10;
#endif
const int M = 7e6+10;
int n, m, prv_u[N][N], prv_d[N][N], prv_l[N][N], prv_r[N][N];
vector<int> sorted_ups[N], sorted_rights[N];
vector<int> ups[N][N], rights[N][N];
vector<int> can_ups[N][N], can_rights[N][N];
long long count_rectangles(vector<vector<int>> a) {
n = sz(a), m = sz(a[0]);
memset(prv_u, -1, sizeof(prv_u));
memset(prv_d, -1, sizeof(prv_d));
memset(prv_l, -1, sizeof(prv_l));
memset(prv_r, -1, sizeof(prv_r));
for (int i = 0; i < n; i++) {
vector<int> stk;
for (int j = 0; j < m; j++) {
while (sz(stk) && a[stk.back() / m][stk.back() % m] <= a[i][j]) stk.pop_back();
if (sz(stk)) prv_l[i][j] = stk.back();
stk.push_back(i * m + j);
}
}
for (int i = 0; i < n; i++) {
vector<int> stk;
for (int j = m-1; j >= 0; j--) {
while (sz(stk) && a[stk.back() / m][stk.back() % m] < a[i][j]) stk.pop_back();
if (sz(stk)) prv_r[i][j] = stk.back();
stk.push_back(i * m + j);
}
}
for (int j = 0; j < m; j++) {
vector<int> stk;
for (int i = 0; i < n; i++) {
while (sz(stk) && a[stk.back() / m][stk.back() % m] <= a[i][j]) stk.pop_back();
if (sz(stk)) prv_u[i][j] = stk.back();
stk.push_back(i * m + j);
}
}
for (int j = 0; j < m; j++) {
vector<int> stk;
for (int i = n-1; i >= 0; i--) {
while (sz(stk) && a[stk.back() / m][stk.back() % m] < a[i][j]) stk.pop_back();
if (sz(stk)) prv_d[i][j] = stk.back();
stk.push_back(i * m + j);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (prv_d[i][j] == -1 || a[prv_d[i][j] / m][prv_d[i][j] % m] <= a[i][j]) continue;
if (prv_u[i][j] == -1 || a[prv_u[i][j] / m][prv_u[i][j] % m] <= a[i][j]) continue;
sorted_ups[prv_u[i][j] / m].push_back(prv_d[i][j]);
// ups[prv_d[i][j] / m][prv_d[i][j] % m].push_back(prv_u[i][j] / m);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (prv_l[i][j] == -1 || a[prv_l[i][j] / m][prv_l[i][j] % m] <= a[i][j]) continue;
if (prv_r[i][j] == -1 || a[prv_r[i][j] / m][prv_r[i][j] % m] <= a[i][j]) continue;
sorted_rights[prv_r[i][j] % m].push_back(prv_l[i][j]);
// rights[prv_l[i][j] / m][prv_l[i][j] % m].push_back(prv_r[i][j] % m);
}
}
for (int i = 0; i < n; i++) {
for (int c : sorted_ups[i]) {
ups[c / m][c % m].push_back(i);
}
}
for (int i = 0; i < m; i++) {
for (int c : sorted_rights[i]) {
rights[c / m][c % m].push_back(i);
}
}
for (int i = 0; i < n; i++) {
unordered_map<int, int> far; // TODO: make array
for (int j = m-1; j >= 0; j--) {
int k = sz(ups[i][j]);
can_ups[i][j].resize(k);
for (int c = 0; c < k; c++) {
can_ups[i][j][c] = far.count(ups[i][j][c]) ? far[ups[i][j][c]] : j;
}
far.clear();
for (int c = 0; c < k; c++)
far[ups[i][j][c]] = can_ups[i][j][c];
}
}
for (int j = 0; j < m; j++) {
unordered_map<int, int> far; // TODO: make array
for (int i = 0; i < n; i++) {
int k = sz(rights[i][j]);
can_rights[i][j].resize(k);
for (int c = 0; c < k; c++) {
can_rights[i][j][c] = far.count(rights[i][j][c]) ? far[rights[i][j][c]] : i;
}
far.clear();
for (int c = 0; c < k; c++)
far[rights[i][j][c]] = can_rights[i][j][c];
}
}
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < m; j++) {
// if (sz(ups[i][j])) {
// cerr << "ups: " << i << ' ' << j << endl;
// for (int c : ups[i][j]) cerr << c << ' ';
// cerr << endl;
// }
// }
// }
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < m; j++) {
// if (sz(rights[i][j])) {
// cerr << "rights: " << i << ' ' << j << endl;
// for (int c : rights[i][j]) cerr << c << ' ';
// cerr << endl;
// }
// }
// }
ll ans = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < m-1; j++) {
int k1 = sz(ups[i][j+1]);
int k2 = sz(rights[i-1][j]);
for (int a = 0; a < k1; a++) {
for (int b = 0; b < k2; b++) {
// if (i == 2 && j == 2 && ups[i][j+1][a] == 0 && rights[i-1][j][b] == 4) {
// cerr << "HERE: " << can_rights[i-1][j][b] << ' ' << can_ups[i][j+1][a] << endl;
// }
if (ups[i][j+1][a] >= can_rights[i-1][j][b] - 1 && rights[i-1][j][b] <= can_ups[i][j+1][a] + 1) {
// cout << ups[i][j+1][a] << ' ' << i << ' ' << j << ' ' << rights[i-1][j][b] << endl;
ans++;
}
}
}
}
}
return ans;
}
# | 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... |