제출 #829037

#제출 시각아이디문제언어결과실행 시간메모리
829037PurpleCrayonRectangles (IOI19_rect)C++17
72 / 100
1740 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; const int N = 2.5e3+10; int n, m, prv_u[N][N], prv_d[N][N], prv_l[N][N], prv_r[N][N]; vector<int> sorted[N]; vector<short> ups[N][N], rights[N][N]; vector<short> can_ups[N][N], can_rights[N][N]; int far[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[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 c : sorted[i]) { ups[c / m][c % m].push_back(i); } vector<int>().swap(sorted[i]); } 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[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 < m; i++) { for (int c : sorted[i]) { rights[c / m][c % m].push_back(i); } vector<int>().swap(sorted[i]); } for (int i = 0; i < n; i++) { memset(far, -1, sizeof(far)); 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[ups[i][j][c]] != -1 ? far[ups[i][j][c]] : j; } if (j < m-1) { for (int c = 0; c < sz(ups[i][j+1]); c++) far[ups[i][j+1][c]] = -1; } for (int c = 0; c < k; c++) far[ups[i][j][c]] = can_ups[i][j][c]; } } for (int j = 0; j < m; j++) { memset(far, -1, sizeof(far)); 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[rights[i][j][c]] != -1 ? far[rights[i][j][c]] : i; } if (i > 0) { for (int c = 0; c < sz(rights[i-1][j]); c++) far[rights[i-1][j][c]] = -1; } 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...