Submission #769716

#TimeUsernameProblemLanguageResultExecution timeMemory
769716SanguineChameleonRectangles (IOI19_rect)C++17
59 / 100
5085 ms700884 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;

const int maxn = 2.5e3 + 20;
int a[maxn][maxn];
int mx[maxn];
int streak[maxn];
vector<pair<int, int>> cand_left[maxn][maxn];
vector<pair<int, int>> cand_up[maxn][maxn];
vector<pair<int, int>> row_queries[maxn][maxn];
vector<pair<int, int>> col_queries[maxn][maxn];
int n, m;

void add_left(int row, int lt, int rt) {
	if (lt > rt) {
		return;
	}
	row_queries[lt][rt].emplace_back(row, cand_left[row][lt].size());
	cand_left[row][lt].emplace_back(rt - lt + 1, -1);
}

void find_left(int row) {
	vector<int> q;
	for (int i = 1; i <= m; i++) {
		while (!q.empty() && a[row][i] > a[row][q.back()]) {
			q.pop_back();
		}
		if (!q.empty() && a[row][i] < a[row][q.back()]) {
			add_left(row, q.back() + 1, i - 1);
		}
		q.push_back(i);
	}
	q.clear();
	for (int i = m; i >= 1; i--) {
		while (!q.empty() && a[row][i] > a[row][q.back()]) {
			q.pop_back();
		}
		if (!q.empty()) {
			add_left(row, i + 1, q.back() - 1);
		}
		q.push_back(i);
	}
}

void add_up(int col, int lt, int rt) {
	if (lt > rt) {
		return;
	}
	col_queries[lt][rt].emplace_back(col, cand_up[lt][col].size());
	cand_up[lt][col].emplace_back(rt - lt + 1, -1);
}

void find_up(int col) {
	vector<int> q;
	for (int i = 1; i <= n; i++) {
		while (!q.empty() && a[i][col] > a[q.back()][col]) {
			q.pop_back();
		}
		if (!q.empty() && a[i][col] < a[q.back()][col]) {
			add_up(col, q.back() + 1, i - 1);
		}
		q.push_back(i);
	}
	q.clear();
	for (int i = n; i >= 1; i--) {
		while (!q.empty() && a[i][col] > a[q.back()][col]) {
			q.pop_back();
		}
		if (!q.empty()) {
			add_up(col, i + 1, q.back() - 1);
		}
		q.push_back(i);
	}
}

void solve_row() {
	for (int lt = 1; lt <= m; lt++) {
		for (int i = 1; i <= n; i++) {
			mx[i] = 0;
		}
		for (int rt = lt; rt <= m; rt++) {
			streak[n + 1] = 0;
			for (int i = n; i >= 1; i--) {
				mx[i] = max(mx[i], a[i][rt]);
				if (mx[i] < a[i][lt - 1] && mx[i] < a[i][rt + 1]) {
					streak[i] = streak[i + 1] + 1;
				}
				else {
					streak[i] = 0;
				}
			}
			for (auto q: row_queries[lt][rt]) {
				int row = q.first;
				int id = q.second;
				cand_left[row][lt][id].second = streak[row];
			}
		}
	}
}

void solve_col() {
	for (int lt = 1; lt <= n; lt++) {
		for (int i = 1; i <= m; i++) {
			mx[i] = 0;
		}
		for (int rt = lt; rt <= n; rt++) {
			streak[m + 1] = 0;
			for (int i = m; i >= 1; i--) {
				mx[i] = max(mx[i], a[rt][i]);
				if (mx[i] < a[lt - 1][i] && mx[i] < a[rt + 1][i]) {
					streak[i] = streak[i + 1] + 1;
				}
				else {
					streak[i] = 0;
				}
			}
			for (auto q: col_queries[lt][rt]) {
				int col = q.first;
				int id = q.second;
				cand_up[lt][col][id].second = streak[col];
			}
		}
	}
}

long long count_rectangles(vector<vector<int>> _a) {
	n = _a.size();
	m = _a[0].size();
	if (n < 3 || m < 3) {
		return 0;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			a[i][j] = _a[i - 1][j - 1];
		}
	}
	for (int i = 1; i <= n; i++) {
		find_left(i);
	}
	for (int i = 1; i <= m; i++) {
		find_up(i);
	}
	solve_row();
	solve_col();
	int res = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			for (auto p1: cand_left[i][j]) {
				for (auto p2: cand_up[i][j]) {
					if (p1.second >= p2.first && p2.second >= p1.first) {
						res++;
					}
				}
			}
		}
	}
	return res;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...