Submission #769813

#TimeUsernameProblemLanguageResultExecution timeMemory
769813SanguineChameleonRectangles (IOI19_rect)C++17
100 / 100
3835 ms763896 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;

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

void add_left(int row, int lt, int rt, bool ins) {
	if (lt > rt) {
		return;
	}
	if (!ins) {
		cand_left[row][lt].emplace_back(rt - lt + 1, -1);
	}
	else {
		int len = rt - lt + 1;
		vector<pair<int, int>> &cur = cand_left[row][lt];
		int pt = (int)cur.size() - 1;
		while (pt >= 0 && cur[pt].first > len) {
			pt--;
		}
		cur.insert(cur.begin() + pt + 1, make_pair(len, -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, false);
		}
		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, true);
		}
		q.push_back(i);
	}
}

void add_up(int col, int lt, int rt, bool ins) {
	if (lt > rt) {
		return;
	}
	if (!ins) {
		cand_up[lt][col].emplace_back(rt - lt + 1, -1);
	}
	else {
		int len = rt - lt + 1;
		vector<pair<int, int>> &cur = cand_up[lt][col];
		int pt = (int)cur.size() - 1;
		while (pt >= 0 && cur[pt].first > len) {
			pt--;
		}
		cur.insert(cur.begin() + pt + 1, make_pair(len, -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, false);
		}
		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, true);
		}
		q.push_back(i);
	}
}

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);
	}
	for (int i = n; i >= 1; i--) {
		for (int j = 1; j <= m; j++) {
			int pt = 0;
			vector<pair<int, int>> &cur = cand_left[i][j];
			vector<pair<int, int>> &nxt = cand_left[i + 1][j];
			for (int k = 0; k < (int)cur.size(); k++) {
				while (pt < (int)nxt.size() && nxt[pt].first < cur[k].first) {
					pt++;
				}
				if (pt < (int)nxt.size() && nxt[pt].first == cur[k].first) {
					cur[k].second = nxt[pt].second + 1;
				}
				else {
					cur[k].second = 1;
				}
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= 1; j--) {
			int pt = 0;
			vector<pair<int, int>> &cur = cand_up[i][j];
			vector<pair<int, int>> &nxt = cand_up[i][j + 1];
			for (int k = 0; k < (int)cur.size(); k++) {
				while (pt < (int)nxt.size() && nxt[pt].first < cur[k].first) {
					pt++;
				}
				if (pt < (int)nxt.size() && nxt[pt].first == cur[k].first) {
					cur[k].second = nxt[pt].second + 1;
				}
				else {
					cur[k].second = 1;
				}
			}
		}
	}
	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...