[LOJ3177] Rectangular Area of "IOI 2019"

Posted by PyraX on Wed, 14 Aug 2019 10:51:09 +0200

[Title Link]

[Points of Thought]

  • Consider the condition that a region is legitimate, each row of elements should be smaller than the elements on both sides of the row, and each column of elements should be smaller than the elements on both sides of the row.
  • Considering the elements a, ba, Ba and B on the left and right sides of a row, bbb is the first element on the right side of aaa (> a GEQ a (> a) or aaa is the first element on the left side of bbb (> b GEQ B (> b), at least one of them is valid, and the same is listed.
  • We call a pair of location pairs (a,b)(a,b)(a,b) (b) (a, b) that satisfy that one of the elements bbb is the first element larger than aaa on the upper/lower/left/right side of another element aaa is a pair of key location pairs, then the necessary and sufficient condition for a region to be legitimate is that the boundary of each row and column in which it is located is a key location pair.
  • It is noted that the number of key position pairs is O(N * M) O(N times M) O(N * M) level, and enumeration can be considered.
  • The left and right boundaries of the rectrectrectrectangle enumerated are i,j (i < J 2) i,j\(ileq j-2) i,j (i \leq j-2) i,j (((i < J J {i, i,j} Si,j} Si,j, J represents all sets of row numbers that make the location of the iiiiiiiiii column and the location of the jjj JJJ jjj column a key position pair of row numbers, and then there is a set of I J SiSiSiSiSij, j, j, j, j, j, j, j, S_{i,j} |= O(N times M)i _j_S i,j_=O(N *M), and an algorithm with complexity of O (i_j_Si,j) O (sum_{i}sum_j | S_{i,j} |) O (i J Si,j) is obtained.
  • So, we just need to calculate how many (x,y)(x,y)(x,y) rows are located so that the set of column numbers where rows xxx and yyy are located as a key position pair contains i+1,i+2,... J_1i+1,i+2, dots, j-1i+1,i+2,... J_1 is enough. The key position pairs in column j_1j-1j_1 can be enumerated directly by O (S i, j) O(| S_{i, j} |) O (Si,j), and the prefix can be pre-processed and judged to include i+1,i+2,... J_1i+1,i+2, dots, j-1i+1,i+2,... All elements in j_1.
  • Time complexity O(N*M)O(Ntimes M)O(N*M).

[Code]

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2505;
typedef long long ll;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
int n, m, a[MAXN][MAXN];
int l[MAXN][MAXN], r[MAXN][MAXN];
int u[MAXN][MAXN], d[MAXN][MAXN];
int lu[MAXN][MAXN], ld[MAXN][MAXN];
vector <int> pos[MAXN][MAXN];
void calclrud() {
	for (int i = 1; i <= n; i++) {
		vector <pair <int, int>> s;
		for (int j = 1; j <= m; j++) {
			while (!s.empty() && s.back().second < a[i][j]) s.pop_back();
			if (!s.empty()) l[i][j] = s.back().first;
			s.emplace_back(j, a[i][j]);
		}
	}
	for (int i = 1; i <= n; i++) {
		vector <pair <int, int>> s;
		for (int j = m; j >= 1; j--) {
			while (!s.empty() && s.back().second < a[i][j]) s.pop_back();
			if (!s.empty()) r[i][j] = s.back().first;
			s.emplace_back(j, a[i][j]);
		}
	}
	for (int j = 1; j <= m; j++) {
		vector <pair <int, int>> s;
		for (int i = 1; i <= n; i++) {
			while (!s.empty() && s.back().second < a[i][j]) s.pop_back();
			if (!s.empty()) u[i][j] = s.back().first;
			s.emplace_back(i, a[i][j]);
		}
	}
	for (int j = 1; j <= m; j++) {
		vector <pair <int, int>> s;
		for (int i = n; i >= 1; i--) {
			while (!s.empty() && s.back().second < a[i][j]) s.pop_back();
			if (!s.empty()) d[i][j] = s.back().first;
			s.emplace_back(i, a[i][j]);
		}
	}
	for (int j = 1; j <= m; j++) {
		for (int i = 1; i <= n; i++) {
			int ql = u[i][j], qr = i;
			if (u[qr][j - 1] == ql) lu[i][j] = lu[qr][j - 1] + 1;
			else if (d[ql][j - 1] == qr) lu[i][j] = ld[ql][j - 1] + 1;
			else lu[i][j] = 1;
			ql = i, qr = d[i][j];
			if (u[qr][j - 1] == ql) ld[i][j] = lu[qr][j - 1] + 1;
			else if (d[ql][j - 1] == qr) ld[i][j] = ld[ql][j - 1] + 1;
			else ld[i][j] = 1;
		}
	} 
}
int main() {
	//string trash; cin >> trash;
	read(n), read(m);
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++)
		read(a[i][j]);
	calclrud();
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++) {
		if (r[i][j]) pos[j][r[i][j]].push_back(i);
		if (l[i][j] && a[i][j] != a[i][l[i][j]]) pos[l[i][j]][j].push_back(i);
	}
	int ans = 0;
	for (int i = 1; i <= m; i++)
	for (int j = i + 2; j <= m; j++) {
		int last = 0, len = 0;
		for (auto y : pos[i][j]) {
			if (y == last + 1) len++;
			else len = 1;
			last = y; int x = y + 1;
			if (x <= n && u[x][j - 1] && x - u[x][j - 1] - 1 <= len && x != u[x][j - 1] + 1 && lu[x][j - 1] >= j - i - 1) ans++;
		}
		reverse(pos[i][j].begin(), pos[i][j].end());
		last = n + 1, len = 0;
		for (auto y : pos[i][j]) {
			if (y == last - 1) len++;
			else len = 1;
			last = y; int x = y - 1;
			if (x >= 1 && d[x][j - 1] && d[x][j - 1] - x - 1 <= len && x != d[x][j - 1] - 1 && a[x][j - 1] != a[d[x][j - 1]][j - 1] && ld[x][j - 1] >= j - i - 1) ans++;
		}
	}
	writeln(ans);
	return 0;
}