Submission #470375

#TimeUsernameProblemLanguageResultExecution timeMemory
470375tutisRectangles (IOI19_rect)C++17
72 / 100
5051 ms441328 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;
long long count_rectangles(vector<vector<int> > a) {
	int n = a.size();
	int m = a[0].size();
	vector<vector<int>> j2(n, vector<int>(m, -1));
	vector<vector<int>> j1(n, vector<int>(m, -1));
	vector<vector<int>> i2(n, vector<int>(m, -1));
	vector<vector<int>> i1(n, vector<int>(m, -1));
	for (int i = 0; i < n; i++)
	{
		vector<int>A;
		for (int j = 0; j < m; j++)
		{
			while (A.size() > 0 && a[i][A.back()] < a[i][j])
				A.pop_back();
			if (!A.empty())
				if (A.back() + 1 <= j - 1)
					j1[i][j] = A.back();
			A.push_back(j);
		}
		A.clear();
		for (int j = m - 1; j >= 0; j--)
		{
			while (A.size() > 0 && a[i][A.back()] < a[i][j])
				A.pop_back();
			if (!A.empty())
				if (j + 1 <= A.back() - 1)
					j2[i][j] = A.back();
			A.push_back(j);
		}
	}
	for (int j = 0; j < m; j++)
	{
		vector<int>A;
		for (int i = 0; i < n; i++)
		{
			while (A.size() > 0 && a[A.back()][j] < a[i][j])
				A.pop_back();
			if (!A.empty())
			{
				if (A.back() + 1 <= i - 1)
					i1[i][j] = A.back();
				else
					i1[i][j] = -1;
			}
			else
				i1[i][j] = -1;
			A.push_back(i);
		}
		A.clear();
		for (int i = n - 1; i >= 0; i--)
		{
			while (A.size() > 0 && a[A.back()][j] < a[i][j])
				A.pop_back();
			if (!A.empty())
			{
				if (i + 1 <= A.back() - 1)
					i2[i][j] = A.back();
				else
					i2[i][j] = -1;
			}
			else
				i2[i][j] = -1;
			A.push_back(i);
		}
	}
	vector<vector<int>> dpi1(n, vector<int>(m, n + 1));
	vector<vector<int>> dpi2(n, vector<int>(m, n + 1));
	vector<vector<int>> dpj1(m, vector<int>(n, m + 1));
	vector<vector<int>> dpj2(m, vector<int>(n, m + 1));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			int j_ = j2[i][j];
			if (j_ != -1)
			{
				dpi1[i][j] = i;
				if (i != 0)
				{
					if (j2[i - 1][j] == j_)
						dpi1[i][j] = dpi1[i - 1][j];
					if (j1[i - 1][j_] == j)
						dpi1[i][j] = dpi2[i - 1][j_];
				}
			}
		}
		for (int j = m - 1; j >= 0; j--)
		{
			int j_ = j1[i][j];
			if (j_ != -1)
			{
				dpi2[i][j] = i;
				if (i != 0)
				{
					if (j1[i - 1][j] == j_)
						dpi2[i][j] = dpi2[i - 1][j];
					if (j2[i - 1][j_] == j)
						dpi2[i][j] = dpi1[i - 1][j_];
				}
			}
		}
	}
	for (int j = 0; j < m; j++)
	{
		for (int i = 0; i < n; i++)
		{
			int i_ = i2[i][j];
			if (i_ != -1)
			{
				dpj1[j][i] = j;
				if (j != 0)
				{
					if (i2[i][j - 1] == i_)
						dpj1[j][i] = dpj1[j - 1][i];
					if (i1[i_][j - 1] == i)
						dpj1[j][i] = dpj2[j - 1][i_];
				}
			}
		}
		for (int i = n - 1; i >= 0; i--)
		{
			int i_ = i1[i][j];
			if (i_ != -1)
			{
				dpj2[j][i] = j;
				if (j != 0)
				{
					if (i1[i][j - 1] == i_)
						dpj2[j][i] = dpj2[j - 1][i];
					if (i2[i_][j - 1] == i)
						dpj2[j][i] = dpj1[j - 1][i_];
				}
			}
		}
	}
	long long ans = 0;
	set<tuple<int, int, int, int>>S;
	auto check = [&](int x1, int x2, int y1, int y2)->void
	{
		if (x1 == -1 || x2 == -1 || y1 == -1 || y2 == -1)
			return;
		if (S.count({x1, x2, y1, y2}))
		return;
		S.insert({x1, x2, y1, y2});
		for (int i : {x1 + 1, x2 - 1})
		{
			if (j2[i][y1] != y2 && j1[i][y2] != y1)
				return;
		}
		for (int j : {y1 + 1, y2 - 1})
		{
			if (i2[x1][j] != x2 && i1[x2][j] != x1)
				return;
		}
		if (j2[x2 - 1][y1] == y2)
		{
			if (dpi1[x2 - 1][y1] > x1 + 1)
				return;
		}
		else
		{
			if (dpi2[x2 - 1][y2] > x1 + 1)
				return;
		}
		if (i2[x1][y2 - 1] == x2)
		{
			if (dpj1[y2 - 1][x1] > y1 + 1)
				return;
		}
		else
		{
			if (dpj2[y2 - 1][x2] > y1 + 1)
				return;
		}
		ans++;
	};
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (j != 0 && j != m - 1)
				for (int i_ : {i1[i][j], i2[i][j]})
				{
					if (i_ == -1)
						continue;
					int x1 = i;
					int x2 = i_;
					if (x1 > x2)
						swap(x1, x2);
					check(x1, x2, j - 1, j2[x1 + 1][j - 1]);
					check(x1, x2, j1[x1 + 1][j + 1], j + 1);
				}
		}
	}
	return ans;
}
// int main()
// {
// 	cout << count_rectangles({{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}) << endl;
// }
#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...