This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/*
ID: varunra2
LANG: C++
TASK: rectangles
*/
#include <bits/stdc++.h>
using namespace std;
#ifdef DEBUG
#include "lib/debug.h"
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define debug_arr(...) \
cerr << "[" << #__VA_ARGS__ << "]:", debug_arr(__VA_ARGS__)
#pragma GCC diagnostic ignored "-Wsign-compare"
//#pragma GCC diagnostic ignored "-Wunused-parameter"
//#pragma GCC diagnostic ignored "-Wunused-variable"
#else
#define debug(...) 42
#endif
#define EPS 1e-9
#define IN(A, B, C) assert(B <= A && A <= C)
#define INF (int)1e9
#define MEM(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define MP make_pair
#define PB push_back
#define all(cont) cont.begin(), cont.end()
#define rall(cont) cont.end(), cont.begin()
#define x first
#define y second
const double PI = acos(-1.0);
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
typedef map<int, int> MPII;
typedef multiset<int> MSETI;
typedef set<int> SETI;
typedef set<string> SETS;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef vector<VI> VVI;
typedef vector<string> VS;
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto& a : x)
#define sz(x) (int)(x).size()
typedef pair<int, int> pii;
typedef vector<int> vi;
#pragma GCC diagnostic ignored "-Wsign-compare"
// util functions
struct timeit {
decltype(chrono::high_resolution_clock::now()) begin;
const string _label;
timeit(string label = "???") : _label(label) { start(); }
void start() { begin = chrono::high_resolution_clock::now(); }
void stop() {
auto end = chrono::high_resolution_clock::now();
auto duration =
chrono::duration_cast<chrono::milliseconds>(end - begin).count();
ostringstream dur;
dur << duration << "ms elapsed [" << _label << "]";
debug(dur.str());
}
};
int n, m;
bool sub6 = false;
void res(VVI& a, int n, int m) {
a.resize(n);
trav(x, a) x.resize(m);
}
void deb(VVI& a) {
debug("debugging");
trav(x, a) debug(x);
}
struct BIT {
VI fen;
int n;
void init(int _n) {
n = _n;
fen.resize(n);
}
void upd(int ind, int val = 1) {
ind++;
while (ind <= n) {
fen[ind - 1] += val;
ind += (ind & -ind);
}
}
int qry(int ind) {
int ret = 0;
ind++;
while (ind >= 1) {
ret += fen[ind - 1];
ind -= (ind & -ind);
}
return ret;
}
int qry(int l, int r) {
r = min(r, n - 1);
l = max(l, 0);
if (r < l) return 0;
return qry(r) - qry(l - 1);
}
};
struct sptable {
const int bits = 20;
int n;
VI log2;
VVI spt;
int id;
void init(VI& vals, int ID) {
id = ID;
n = sz(vals);
log2.resize(n + 1);
res(spt, n, bits);
log2[1] = 0;
for (int i = 2; i <= n; i++) {
log2[i] = log2[i / 2] + 1;
}
for (int i = 0; i < n; i++) {
spt[i][0] = vals[i];
}
for (int i = 1; i < bits; i++) {
for (int j = 0; j + (1 << i) <= n; j++) {
int val1 = spt[j][i - 1];
int val2 = spt[j + (1 << (i - 1))][i - 1];
if (id)
spt[j][i] = max(val1, val2);
else
spt[j][i] = min(val1, val2);
}
}
}
int qry(int l, int r) {
int j = log2[r - l + 1];
int val1 = spt[l][j];
int val2 = spt[r - (1 << j) + 1][j];
if (id) return max(val1, val2);
return min(val1, val2);
}
void deb() { trav(x, spt) debug(x); }
};
VII gen(VI& vals) {
VII ret;
// generate the possible sides in this row
VI inds;
for (int i = 0; i < sz(vals); i++) {
for (int j = sz(inds) - 1; j >= 0; j--) {
int ind = inds[j];
if (vals[ind] >= vals[i]) {
if (i - ind >= 2) ret.PB(MP(ind, i));
break;
} else {
if (i - ind >= 2) ret.PB(MP(ind, i));
}
// if(j > 0 and vals[inds[j - 1]] == vals[ind]) break;
}
while (!inds.empty() and vals[inds.back()] <= vals[i]) inds.pop_back();
inds.PB(i);
}
return ret;
}
VVI grid;
VVI igrid;
VVI nxt;
VVI prv;
vector<sptable> spmx;
vector<sptable> spmn;
void init(VVI& a) {
res(grid, n, m);
res(igrid, m, n);
res(nxt, n, m);
res(prv, n, m);
spmx.resize(n);
spmn.resize(n);
rep(i, 0, n) rep(j, 0, m) {
grid[i][j] = a[i][j];
igrid[j][i] = a[i][j];
}
}
VI genprv(VI& vals) {
// get first element before you strictly greater than you
VI ret(sz(vals));
stack<int> st;
for (int i = 0; i < sz(vals); i++) {
while (!st.empty() and vals[st.top()] < vals[i]) st.pop();
if (st.empty())
ret[i] = -1;
else
ret[i] = st.top();
st.push(i);
}
return ret;
}
VI gennxt(VI& vals) {
VI ret(sz(vals));
stack<int> st;
for (int i = sz(vals) - 1; ~i; i--) {
while (!st.empty() and vals[st.top()] < vals[i]) st.pop();
if (st.empty())
ret[i] = n;
else
ret[i] = st.top();
st.push(i);
}
return ret;
}
ll solve(int l, int r, int s, int e) {
if (r - l < 2) return 0ll;
// timeit solv("solve function");
// left, right, start, end
// this describes a rectangle
// we must solve this rectangle
ll ret = 0;
// we will solve it using a sweepline approach
VVI sweep;
BIT fen;
fen.init(e - s + 1);
// we have a few types of events
for (int i = s; i <= e; i++) {
// we have to calculate this element at some point in time
sweep.PB({i, 0});
}
for (int i = s; i <= e; i++) {
sweep.PB({spmx[i + 1].qry(l + 1, r - 1), 1, i});
}
sort(all(sweep));
reverse(all(sweep));
for (int i = 0; i < e - s + 1; i++) {
fen.upd(i, 1);
}
for (auto& x : sweep) {
int val, type;
val = x[0];
type = x[1];
if (val < s) break;
if (type == 1) {
fen.upd(x[2] - s, -1);
} else {
int ind = spmn[val - 1].qry(l + 1, r - 1) - 1;
// debug(ind);
// debug(val - 1);
// ind = INF;
// for (int i = l + 1; i <= r - 1; i++) {
// ind = min(ind, nxt[val - 1][i]);
// }
// ind--;
ret += fen.qry(val - s, min(ind, e) - s);
}
}
// this is not possible :thonk:
// [sweep]: {{6, 1, 6}, {6, 0}, {5, 0}, {4, 1, 5}, {4, 1, 4}, {4, 0}, {3, 1,
// 3}, {3, 0}} [l, r, s, e]: 4 7 3 6 [ret]: -1
// debug(sweep);
// debug(l, r, s, e);
// debug(ret);
// solv.stop();
return ret;
}
VVI pref;
void build(VVI& a) {
res(pref, n, m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
pref[i][j] = a[i][j];
if (i) pref[i][j] += pref[i - 1][j];
if (j) pref[i][j] += pref[i][j - 1];
if (i and j) pref[i][j] -= pref[i - 1][j - 1];
}
}
}
int qry(int a, int b, int c, int d) {
int ret = 0;
ret += pref[c][d];
if (a) ret -= pref[a - 1][d];
if (b) ret -= pref[c][b - 1];
if (a and b) ret += pref[a - 1][b - 1];
return ret;
}
ll solvesub6(VVI& a) {
int ret = 0;
vector<vector<bool>> vis(n, vector<bool>(m, false));
build(a);
for (int i = 1; i < n - 1; i++) {
for (int j = 1; j < m - 1; j++) {
// debug(i, j);
if (vis[i][j]) continue;
if (a[i][j]) continue;
int p1 = i;
vis[i][j] = true;
while (p1 + 1 < n - 1 and a[p1 + 1][j] == 0) {
p1++;
if (vis[p1][j]) {
p1--;
break;
}
vis[p1][j] = true;
debug(p1);
}
int p2 = j;
while (p2 + 1 < m - 1 and a[p1][p2 + 1] == 0) {
p2++;
if (vis[p1][p2]) {
p2--;
break;
}
vis[p1][p2] = true;
debug(p2);
}
debug(i, j, p1, p2);
// if (p1 - i < 2 or p2 - j < 2) continue;
// debug(i, j, p1, p2);
// int val1 = qry(i, j, p1, p2);
// int val2 = qry(i - 1, j - 1, p1 + 1, p2 + 1);
// int goal1 = 0;
// int goal2 = 2 * (p1 - i + p2 - j + 2);
// if (val1 == goal1 and val2 == goal2) ret++;
bool ok = true;
for (int k = i; k <= p1 and ok; k++) {
for (int l = j; l <= p2; l++) {
if (a[k][l] and !vis[k][l]) {
ok = false;
// debug("type 1");
break;
}
vis[k][l] = true;
}
}
// debug("here1");
for (int k = i; k <= p1 and ok; k++) {
if (!a[k][j - 1] or !a[k][p2 + 1]) {
ok = false;
// debug("type 2");
break;
}
}
// debug("here2");
for (int k = j; k <= p2 and ok; k++) {
if (!a[i - 1][k] or !a[p1 + 1][k]) {
ok = false;
// debug("type 3");
break;
}
}
// debug("here3");
if (ok) ret++;
}
}
return ret;
}
ll count_rectangles(VVI a) {
// timeit slv("solving");
n = sz(a);
m = sz(a[0]);
int mx = 0;
trav(x, a) trav(y, x) mx = max(mx, y);
if (mx <= 1) sub6 = true;
if (sub6) return solvesub6(a);
init(a);
vector<VII> pos(n);
for (int i = 0; i < n; i++) {
pos[i] = gen(grid[i]);
}
// timeit prvnxt("genning prv/nxt and sp table");
for (int i = 0; i < m; i++) {
auto pr = genprv(igrid[i]);
auto nx = gennxt(igrid[i]);
for (int j = 0; j < n; j++) {
prv[j][i] = pr[j];
nxt[j][i] = nx[j];
}
}
for (int i = 0; i < n; i++) {
spmn[i].init(nxt[i], 0);
spmx[i].init(prv[i], 1);
}
// prvnxt.stop();
vector<map<PII, bool>> there(n);
for (int i = 1; i < n - 1; i++) {
trav(x, pos[i]) there[i][x] = true;
}
// deb(prv);
// deb(nxt);
ll ret = 0;
// const PII bad1 = MP(2, 4);
// const int bad2 = 3;
// timeit log("finding rectangles");
for (int i = 1; i < n - 1; i++) {
// timeit fori("for a single i");
int cnt = 0;
for (auto& x : pos[i]) {
// debug(i, x);
int e = i;
if (there[i][x] == false) continue;
for (int j = i; j < n - 1; j++) {
cnt++;
// if (x == bad1 and i == bad2) debug("here1", x, i, j);
if (there[j][x] == false) break;
// if (x == bad1 and i == bad2) debug("here", x, i, j);
there[j][x] = false;
e = j;
}
ll cur = solve(x.x, x.y, i, e);
ret += cur;
// if (cur > 0) debug(cur, x.x, x.y, i, e);
}
// fori.stop();
// debug(cnt);
// debug(sz(pos[i]));
}
// log.stop();
const int bad = 3;
// spmn[bad].deb();
// debug(spmn[bad].qry(2, 3));
// slv.stop();
return ret;
}
Compilation message (stderr)
rect.cpp: In member function 'void timeit::stop()':
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:66:5: note: in expansion of macro 'debug'
66 | debug(dur.str());
| ^~~~~
rect.cpp: In function 'void deb(VVI&)':
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:80:3: note: in expansion of macro 'debug'
80 | debug("debugging");
| ^~~~~
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:81:14: note: in expansion of macro 'debug'
81 | trav(x, a) debug(x);
| ^~~~~
rect.cpp:31:11: warning: unused variable 'first' [-Wunused-variable]
31 | #define x first
| ^~~~~
rect.cpp:48:31: note: in definition of macro 'trav'
48 | #define trav(a, x) for (auto& a : x)
| ^
rect.cpp:81:8: note: in expansion of macro 'x'
81 | trav(x, a) debug(x);
| ^
rect.cpp: In member function 'void sptable::deb()':
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:155:29: note: in expansion of macro 'debug'
155 | void deb() { trav(x, spt) debug(x); }
| ^~~~~
rect.cpp:31:11: warning: unused variable 'first' [-Wunused-variable]
31 | #define x first
| ^~~~~
rect.cpp:48:31: note: in definition of macro 'trav'
48 | #define trav(a, x) for (auto& a : x)
| ^
rect.cpp:155:21: note: in expansion of macro 'x'
155 | void deb() { trav(x, spt) debug(x); }
| ^
rect.cpp: In function 'll solvesub6(VVI&)':
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:325:9: note: in expansion of macro 'debug'
325 | debug(p1);
| ^~~~~
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:335:9: note: in expansion of macro 'debug'
335 | debug(p2);
| ^~~~~
rect.cpp:19:20: warning: statement has no effect [-Wunused-value]
19 | #define debug(...) 42
| ^~
rect.cpp:338:7: note: in expansion of macro 'debug'
338 | debug(i, j, p1, p2);
| ^~~~~
rect.cpp: In function 'll count_rectangles(VVI)':
rect.cpp:467:13: warning: unused variable 'bad' [-Wunused-variable]
467 | const int bad = 3;
| ^~~
# | 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... |