Submission #1078135

#TimeUsernameProblemLanguageResultExecution timeMemory
1078135BoasRectangles (IOI19_rect)C++17
37 / 100
1347 ms1048576 KiB
#include "rect.h" #include <bits/stdc++.h> using namespace std; // #define int long long #define sz(x) (int)x.size() #define pb push_back #define loop(x, i) for (int i = 0; i < x; i++) #define rev(x, i) for (int i = (int)x - 1; i >= 0; i--) #define ALL(x) begin(x), end(x) typedef signed i32; typedef pair<int, int> ii; typedef vector<i32> vi32; typedef vector<int> vi; typedef vector<ii> vii; typedef vector<bool> vb; typedef vector<vi> vvi; typedef vector<vvi> vvvi; typedef vector<vi32> vvi32; typedef vector<vii> vvii; typedef vector<vb> vvb; typedef vector<vvb> vvvb; long long count_rectangles(vvi a) { int n = sz(a); // h int m = sz(a[0]); // w vvvi validUp(n, vvi(m, vi(m))); vvvi validDown(n, vvi(m, vi(m))); vvvi validL(m, vvi(n, vi(n))); vvvi validR(m, vvi(n, vi(n))); // omwisselen voor cache friendlyness? vvi minL(n, vi(m, 1e9)), minU(n, vi(m, 1e9)), maxR(n, vi(m, -1)), maxD(n, vi(m, -1)); for (int c = 1; c < m - 1; c++) { for (int r = 1; r < n - 1; r++) { for (int c1 = c; c1 > 0; c1--) { if (a[r][c1] >= a[r][c + 1]) break; minL[r][c] = c1; } for (int c2 = c; c2 < m - 1; c2++) { if (a[r][c2] >= a[r][c - 1]) break; maxR[r][c] = c2; } for (int r1 = r; r1 > 0; r1--) { if (a[r1][c] >= a[r + 1][c]) break; minU[r][c] = r1; } for (int r2 = r; r2 < n - 1; r2++) { if (a[r2][c] >= a[r - 1][c]) break; maxD[r][c] = r2; } } } for (int c = 1; c < m - 1; c++) { for (int r1 = 1; r1 < n - 1; r1++) { int mnL = 0; int mxR = m; for (int r2 = r1; r2 < n - 1; r2++) { mnL = max(mnL, minL[r2][c]); mxR = min(mxR, maxR[r2][c]); validL[c][r1][r2] = mxR; validR[c][r1][r2] = mnL; } } } for (int r = 1; r < n - 1; r++) { for (int c1 = 1; c1 < m - 1; c1++) { int mnU = 0; int mxD = n; for (int c2 = c1; c2 < m - 1; c2++) { mnU = max(mnU, minU[r][c2]); mxD = min(mxD, maxD[r][c2]); validUp[r][c1][c2] = mxD; validDown[r][c1][c2] = mnU; } } } int treeM = 1; while (treeM < m) treeM *= 2; vector<vector<vvi>> tree(n, vvvi(n, vvi(treeM * 2))); // validR is geen voolean meer. het hangt af van l. // merge sort tree bouwen op validR, return count <= l for (int r1 = 1; r1 < n - 1; r1++) { for (int r2 = r1; r2 < n - 1; r2++) { for (int c = 1; c < m - 1; c++) { tree[r1][r2][treeM + c] = {validR[c][r1][r2]}; } rev(treeM, i) { merge(ALL(tree[r1][r2][2 * i]), ALL(tree[r1][r2][2 * i + 1]), back_inserter(tree[r1][r2][i])); } } } auto query = [&](auto &&self, int r1, int r2, int i, int l, int r, int ql, int qr, int v) -> int { int mid = (l + r) / 2; if (qr < l || r < ql) return 0; if (ql <= l && r <= qr) { long int res = upper_bound(ALL(tree[r1][r2][i]), v) - tree[r1][r2][i].begin(); return (int)res; } return self(self, r1, r2, 2 * i, l, mid, ql, qr, v) + self(self, r1, r2, 2 * i + 1, mid + 1, r, ql, qr, v); }; long long res = 0; for (int c = 1; c < m - 1; c++) { for (int r1 = 1; r1 < n - 1; r1++) { for (int r2 = r1; r2 < n - 1; r2++) { int mxR = validL[c][r1][r2]; if (mxR == -1) break; int lo = c, hi = mxR; int ans = -1; while (hi >= lo) { int c2 = (lo + hi) / 2; if (validUp[r1][c][c2] >= r2 && validDown[r2][c][c2] <= r1) { ans = c2; lo = c2 + 1; } else { hi = c2 - 1; } } if (ans == -1) continue; res += query(query, r1, r2, 1, 0, treeM - 1, c, ans, c); } } } 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...