제출 #829034

#제출 시각아이디문제언어결과실행 시간메모리
829034PurpleCrayonRectangles (IOI19_rect)C++17
72 / 100
2578 ms1048576 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;

#define sz(v) int(v.size())
#define ar array
typedef long long ll;

#ifdef LOCAL
const int N = 1e2;
#endif

#ifndef LOCAL
const int N = 2.5e3+10;
#endif

const int M = 7e6+10;

int n, m, prv_u[N][N], prv_d[N][N], prv_l[N][N], prv_r[N][N];
vector<int> sorted_ups[N], sorted_rights[N];
vector<int> ups[N][N], rights[N][N];
vector<int> can_ups[N][N], can_rights[N][N];

long long count_rectangles(vector<vector<int>> a) {
	n = sz(a), m = sz(a[0]);

	memset(prv_u, -1, sizeof(prv_u));
	memset(prv_d, -1, sizeof(prv_d));
	memset(prv_l, -1, sizeof(prv_l));
	memset(prv_r, -1, sizeof(prv_r));
	for (int i = 0; i < n; i++) {
		vector<int> stk;
		for (int j = 0; j < m; j++) {
			while (sz(stk) && a[stk.back() / m][stk.back() % m] <= a[i][j]) stk.pop_back();
			if (sz(stk)) prv_l[i][j] = stk.back();
			stk.push_back(i * m + j);
		}
	}

	for (int i = 0; i < n; i++) {
		vector<int> stk;
		for (int j = m-1; j >= 0; j--) {
			while (sz(stk) && a[stk.back() / m][stk.back() % m] < a[i][j]) stk.pop_back();
			if (sz(stk)) prv_r[i][j] = stk.back();
			stk.push_back(i * m + j);
		}
	}

	for (int j = 0; j < m; j++) {
		vector<int> stk;
		for (int i = 0; i < n; i++) {
			while (sz(stk) && a[stk.back() / m][stk.back() % m] <= a[i][j]) stk.pop_back();
			if (sz(stk)) prv_u[i][j] = stk.back();
			stk.push_back(i * m + j);
		}
	}

	for (int j = 0; j < m; j++) {
		vector<int> stk;
		for (int i = n-1; i >= 0; i--) {
			while (sz(stk) && a[stk.back() / m][stk.back() % m] < a[i][j]) stk.pop_back();
			if (sz(stk)) prv_d[i][j] = stk.back();
			stk.push_back(i * m + j);
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (prv_d[i][j] == -1 || a[prv_d[i][j] / m][prv_d[i][j] % m] <= a[i][j]) continue;
			if (prv_u[i][j] == -1 || a[prv_u[i][j] / m][prv_u[i][j] % m] <= a[i][j]) continue;
			sorted_ups[prv_u[i][j] / m].push_back(prv_d[i][j]);
			// ups[prv_d[i][j] / m][prv_d[i][j] % m].push_back(prv_u[i][j] / m);
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (prv_l[i][j] == -1 || a[prv_l[i][j] / m][prv_l[i][j] % m] <= a[i][j]) continue;
			if (prv_r[i][j] == -1 || a[prv_r[i][j] / m][prv_r[i][j] % m] <= a[i][j]) continue;
			sorted_rights[prv_r[i][j] % m].push_back(prv_l[i][j]);
			// rights[prv_l[i][j] / m][prv_l[i][j] % m].push_back(prv_r[i][j] % m);
		}
	}

	for (int i = 0; i < n; i++) {
		for (int c : sorted_ups[i]) {
			ups[c / m][c % m].push_back(i);
		}
	}

	for (int i = 0; i < m; i++) {
		for (int c : sorted_rights[i]) {
			rights[c / m][c % m].push_back(i);
		}
	}

	for (int i = 0; i < n; i++) {
		unordered_map<int, int> far; // TODO: make array
		for (int j = m-1; j >= 0; j--) {
			int k = sz(ups[i][j]);
			can_ups[i][j].resize(k);

			for (int c = 0; c < k; c++) {
				can_ups[i][j][c] = far.count(ups[i][j][c]) ? far[ups[i][j][c]] : j;
			}

			far.clear();
			for (int c = 0; c < k; c++)
				far[ups[i][j][c]] = can_ups[i][j][c];
		}
	}

	for (int j = 0; j < m; j++) {
		unordered_map<int, int> far; // TODO: make array
		for (int i = 0; i < n; i++) {
			int k = sz(rights[i][j]);
			can_rights[i][j].resize(k);

			for (int c = 0; c < k; c++) {
				can_rights[i][j][c] = far.count(rights[i][j][c]) ? far[rights[i][j][c]] : i;
			}

			far.clear();
			for (int c = 0; c < k; c++)
				far[rights[i][j][c]] = can_rights[i][j][c];
		}
	}

	// for (int i = 0; i < n; i++) {
	// 	for (int j = 0; j < m; j++) {
	// 		if (sz(ups[i][j])) {
	// 			cerr << "ups: " << 	i << ' ' << j << endl;
	// 			for (int c : ups[i][j]) cerr << c << ' ';
	// 			cerr << endl;
	// 		}
	// 	}
	// }

	// for (int i = 0; i < n; i++) {
	// 	for (int j = 0; j < m; j++) {
	// 		if (sz(rights[i][j])) {
	// 			cerr << "rights: " << i << ' ' << j << endl;
	// 			for (int c : rights[i][j]) cerr << c << ' ';
	// 			cerr << endl;
	// 		}
	// 	}
	// }

	ll ans = 0;
	for (int i = 1; i < n; i++) {
		for (int j = 0; j < m-1; j++) {
			int k1 = sz(ups[i][j+1]);
			int k2 = sz(rights[i-1][j]);
			for (int a = 0; a < k1; a++) {
				for (int b = 0; b < k2; b++) {
					// if (i == 2 && j == 2 && ups[i][j+1][a] == 0 && rights[i-1][j][b] == 4) {
					// 	cerr << "HERE: " << can_rights[i-1][j][b] << ' ' << can_ups[i][j+1][a] << endl;
					// }

					if (rights[i-1][j][b] > can_ups[i][j+1][a] + 1) break;
					if (ups[i][j+1][a] >= can_rights[i-1][j][b] - 1) {
						// cout << ups[i][j+1][a] << ' ' << i << ' ' << j << ' ' << rights[i-1][j][b] << endl;
						ans++;
					}
				}
			}
		}
	}

	return ans;
}
#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...