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>
#define int long long
using namespace std;
const int MAXN = 2500;
bool seen[2500][2500];
int DX[] = {-1, 1, 0, 0};
int DY[] = {0, 0, -1, 1};
int nbLig, nbCol;
int maxLig, minLig, minCol, maxCol, nbVus;
int available[MAXN][MAXN];
int ptr[MAXN];
int stk;
int toRemove[MAXN * MAXN];
vector<vector<signed>> val;
template <class T> class Fenwick {
public:
int lim;
vector<T> bit;
Fenwick(int n) : lim(n + 1), bit(lim) {}
void upd(int pos, T v) {
for (pos++; pos < lim; pos += pos & -pos)
bit[pos] += v;
}
T sum(int r) { // < r
T ret = 0;
for (; r; r -= r & -r)
ret += bit[r];
return ret;
}
T sum(int l, int r) { // [l, r)
return sum(r) - sum(l);
}
};
struct maxSeg {
vector<int> seg;
int deb;
maxSeg(int n) {
int p = 0;
while ((1 << p) < n)
++p;
deb = (1 << p);
seg.resize(2 * deb + 1);
}
void upd(int i, int v) {
i += deb;
seg[i] = v;
while (i > 1) {
i /= 2;
seg[i] = max(seg[2 * i], seg[2 * i + 1]);
}
}
int query(int l, int r) {
l += deb, r += deb;
int ret = 0;
while (l < r) {
if (l % 2)
ret = max(ret, seg[l]);
if (r % 2 == 0)
ret = max(ret, seg[r]);
l = (l + 1) / 2;
r = (r - 1) / 2;
}
if (l == r)
ret = max(ret, seg[l]);
return ret;
}
};
struct minSeg {
vector<int> seg;
int deb;
minSeg(int n) {
int p = 0;
while ((1 << p) < n)
++p;
deb = (1 << p);
seg.assign(2 * deb + 1, 1e18);
}
void upd(int i, int v) {
i += deb;
seg[i] = v;
while (i > 1) {
i /= 2;
seg[i] = min(seg[2 * i], seg[2 * i + 1]);
}
}
int query(int l, int r) {
l += deb, r += deb;
int ret = 1e18;
while (l < r) {
if (l % 2)
ret = min(ret, seg[l]);
if (r % 2 == 0)
ret = min(ret, seg[r]);
l = (l + 1) / 2;
r = (r - 1) / 2;
}
if (l == r)
ret = min(ret, seg[l]);
return ret;
}
};
void dfs(int iLig, int iCol) {
if (nbLig <= iLig or iLig < 0 or iCol < 0 or iCol >= nbCol or
seen[iLig][iCol] or val[iLig][iCol])
return;
nbVus++;
maxLig = max(maxLig, iLig);
minLig = min(minLig, iLig);
minCol = min(minCol, iCol);
maxCol = max(maxCol, iCol);
seen[iLig][iCol] = true;
for (int d = 0; d < 4; ++d) {
int col = iCol + DX[d];
int lig = iLig + DY[d];
dfs(lig, col);
}
}
int solveBinary() {
int ret = 0;
for (int iLig = 0; iLig < nbLig; ++iLig)
for (int iCol = 0; iCol < nbCol; ++iCol)
if (!seen[iLig][iCol] and !val[iLig][iCol]) {
minLig = maxLig = iLig;
minCol = maxCol = iCol;
nbVus = 0;
dfs(iLig, iCol);
ret += nbVus == (maxLig - minLig + 1) * (maxCol - minCol + 1) and
maxLig < nbLig - 1 and minLig > 0 and minCol > 0 and
maxCol < nbCol - 1;
}
return ret;
}
long long count_rectangles(vector<vector<signed>> a) {
val = a;
nbLig = a.size(), nbCol = a[0].size();
bool isBinary = true;
for (auto v : a)
for (auto w : v)
isBinary &= w < 2;
if (isBinary)
return solveBinary();
vector<vector<int>> down(nbLig, vector<int>(nbCol));
vector<vector<int>> up(nbLig, vector<int>(nbCol));
vector<vector<int>> right(nbLig, vector<int>(nbCol));
vector<vector<int>> left(nbLig, vector<int>(nbCol));
for (int col = 0; col < nbCol; ++col) {
for (int iLig = nbLig - 1; iLig >= 0; --iLig) {
int nxt = iLig + 1;
while (nxt < nbLig and a[iLig][col] > a[nxt][col])
nxt = down[nxt][col];
down[iLig][col] = nxt;
}
for (int iLig = 0; iLig < nbLig; ++iLig) {
int nxt = iLig - 1;
while (nxt >= 0 and a[iLig][col] > a[nxt][col])
nxt = up[nxt][col];
up[iLig][col] = nxt;
}
}
for (int lig = 0; lig < nbLig; ++lig) {
for (int iCol = nbCol - 1; iCol >= 0; --iCol) {
int nxt = iCol + 1;
while (nxt < nbCol and a[lig][iCol] > a[lig][nxt])
nxt = right[lig][nxt];
right[lig][iCol] = nxt;
}
for (int iCol = 0; iCol < nbCol; ++iCol) {
int nxt = iCol - 1;
while (nxt >= 0 and a[lig][iCol] > a[lig][nxt])
nxt = left[lig][nxt];
left[lig][iCol] = nxt;
}
}
vector<minSeg> segRight(nbCol, minSeg(nbLig));
vector<maxSeg> segLeft(nbCol, maxSeg(nbLig));
for (int iLig = 0; iLig < nbLig; ++iLig)
for (int iCol = 0; iCol < nbCol; ++iCol) {
segRight[iCol].upd(iLig, right[iLig][iCol]);
segLeft[iCol].upd(iLig, left[iLig][iCol]);
}
long long sol = 0;
Fenwick<int> fen(nbCol);
for (int lig1 = 0; lig1 < nbLig; ++lig1)
for (int lig2 = lig1 + 2; lig2 < nbLig; ++lig2) {
fen.bit.assign(fen.lim, 0);
for (int col2 = 2; col2 < nbCol; ++col2) {
int x = max(0LL, segLeft[col2].query(lig1 + 1, lig2 - 1));
if (x < nbCol)
available[x][ptr[x]++] = col2;
}
int col2 = 0;
for (int col1 = 0; col1 < nbCol - 1; ++col1) {
if (col2 <= col1)
col2 = col1 + 1;
while (col2 < nbCol and up[lig2][col2] <= lig1 and
down[lig1][col2] >= lig2)
++col2;
while (ptr[col1])
fen.upd(available[col1][--ptr[col1]], 1);
int bnd = min(nbCol - 1, segRight[col1].query(lig1 + 1, lig2 - 1));
if (col1 + 2 <= min(bnd, col2))
sol += fen.sum(col1 + 2, min(bnd, col2) + 1);
}
}
return sol;
}
# | 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... |