Submission #769717

#TimeUsernameProblemLanguageResultExecution timeMemory
769717SanguineChameleonRectangles (IOI19_rect)C++17
72 / 100
1320 ms1048576 KiB
#include "rect.h" #include <bits/stdc++.h> using namespace std; const int maxn = 2.5e3 + 20; int a[maxn][maxn]; int pref[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; bool sub6; void add_left(int row, int lt, int rt) { if (lt > rt) { return; } if (sub6 && (a[row][lt - 1] == 0 || a[row][rt + 1] == 0)) { 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; } if (sub6 && (a[lt - 1][col] == 0 || a[rt + 1][col] == 0)) { 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]; } } } } int get(int lx, int ly, int rx, int ry) { return pref[rx][ry] - pref[rx][ly - 1] - pref[lx - 1][ry] + pref[lx - 1][ly - 1]; } bool check(int lx, int ly, int rx, int ry) { return get(lx, ly, rx, ry) == 0 && get(lx - 1, ly, lx - 1, ry) == ry - ly + 1 && get(rx + 1, ly, rx + 1, ry) == ry - ly + 1 && get(lx, ly - 1, rx, ly - 1) == rx - lx + 1 && get(lx, ry + 1, rx, ry + 1) == rx - lx + 1; } long long count_rectangles(vector<vector<int>> _a) { n = _a.size(); m = _a[0].size(); if (n < 3 || m < 3) { return 0; } sub6 = true; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { a[i][j] = _a[i - 1][j - 1]; sub6 &= (a[i][j] <= 1); } } for (int i = 1; i <= n; i++) { find_left(i); } for (int i = 1; i <= m; i++) { find_up(i); } if (sub6) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { pref[i][j] = pref[i][j - 1] + a[i][j]; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { pref[i][j] += pref[i - 1][j]; } } 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 (check(i, j, i + p2.first - 1, j + p1.first - 1)) { res++; } } } } } return res; } else { 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...