# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
829041 | PurpleCrayon | Rectangles (IOI19_rect) | C++17 | 0 ms | 0 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;
#define sz(v) int(v.size())
#define ar array
typedef long long ll;
const int N = 2.5e3+10;
int n, m, prv_u[N][N], prv_d[N][N], prv_l[N][N], prv_r[N][N];
vector<int> sorted[N];
vector<short> ups[N][N], rights[N][N];
vector<short> can_ups[N][N], can_rights[N][N];
int far[N];
long long count_rectangles(const 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[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 c : sorted[i]) {
ups[c / m][c % m].push_back(i);
}
vector<int>().swap(sorted[i]);
}
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[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 < m; i++) {
for (int c : sorted[i]) {
rights[c / m][c % m].push_back(i);
}
vector<int>().swap(sorted[i]);
}
for (int i = 0; i < n; i++) {
memset(far, -1, sizeof(far));
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[ups[i][j][c]] != -1 ? far[ups[i][j][c]] : j;
}
if (j < m-1) {
for (int c = 0; c < sz(ups[i][j+1]); c++)
far[ups[i][j+1][c]] = -1;
}
for (int c = 0; c < k; c++)
far[ups[i][j][c]] = can_ups[i][j][c];
}
}
for (int j = 0; j < m; j++) {
memset(far, -1, sizeof(far));
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[rights[i][j][c]] != -1 ? far[rights[i][j][c]] : i;
}
if (i > 0) {
for (int c = 0; c < sz(rights[i-1][j]); c++)
far[rights[i-1][j][c]] = -1;
}
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 (rights[i-1][j][b] > can_ups[i][j+1][a] + 1) break;
if (ups[i][j+1][a] >= can_rights[i-1][j][b] - 1) {
// cout << ups[i][j+1][a] << ' ' << i << ' ' << j << ' ' << rights[i-1][j][b] << endl;
ans++;
}
}
}
}
}
return ans;
}