1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| #include <iostream> #include <vector> #include <algorithm> #include <stack> #include <cmath>
using namespace std;
struct SegmentTree { vector<pair<int, int>> st; int n = 0; SegmentTree(const vector<int>& a) { n = a.size(); int x = ceil(log2(n)); int max_size = std::pow(2, x + 1) - 1; st.resize(max_size);
constructSTUtil(a, 0, n-1, 0); } void constructSTUtil(const vector<int>& arr, int ss, int se, int si) { if (ss == se) { st[si].first = arr[ss]; st[si].second = arr[ss]; return; } int mid = ss + (se - ss) / 2; constructSTUtil(arr, ss, mid, si*2+1); constructSTUtil(arr, mid+1, se, si*2+2); st[si].first = min(st[si*2+1].first, st[si*2+2].first); st[si].second = max(st[si*2+1].second, st[si*2+2].second); }
pair<int, int> maxMinUtil(int ss, int se, int qs, int qe, int index) { if (ss >= qs && se <= qe) { return st[index]; } if (se < qs || ss > qe) { return {numeric_limits<int>::max(), numeric_limits<int>::min()}; } int mid = ss + (se - ss) / 2; auto left = maxMinUtil(ss, mid, qs, qe, index*2+1); auto right = maxMinUtil(mid+1, se, qs, qe, index*2+2); return {min(left.first, right.first), max(left.second, right.second)}; } pair<int, int> maxMin(int qs, int qe) { if (qs < 0 || qe > n - 1 || qs > qe) { cerr << "Invalid Input" << endl; return {numeric_limits<int>::max(), numeric_limits<int>::min()}; } return maxMinUtil(0, n-1, qs, qe, 0); } int queryDiff(int qs, int qe) { auto ans = maxMin(qs, qe); return ans.second - ans.first; } };
int solve(const vector<vector<int>>& board, int K) { int R = board.size(); int C = board[0].size(); vector<vector<int>> heigth(R, vector<int>(C)); for (int i = 0; i < R; ++i) { auto maxMin = SegmentTree(board[i]); for (int j = 0; j < C; ++ j) { int lo = j, hi = C; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (maxMin.queryDiff(j, mid) <= K) { lo = mid + 1; } else { hi = mid; } } heigth[i][j] = lo - j; } } int ans = 0; for (int j = 0; j < C; ++j) { stack<int> s; int i = 0; while (i < R) { if (s.empty() || heigth[s.top()][j] <= heigth[i][j]) { s.push(i); ++i; } else { int tp = s.top(); s.pop(); ans = max(ans, heigth[tp][j] * (s.empty() ? i : i - s.top() - 1)); } } while (!s.empty()) { int tp = s.top(); s.pop(); ans = max(ans, heigth[tp][j] * (s.empty() ? i : i - s.top() - 1)); } } return ans; } int main() { int T; cin >> T; for (int i = 1; i <= T; ++i) { int R, C, K; cin >> R >> C >> K; vector<vector<int>> board(R, vector<int>(C)); for (int j = 0; j < R; ++j) { for (int k = 0; k < C; ++k) { cin >> board[j][k]; } } int ans = solve(board, K); cout << "Case #" << i << ": " << ans << endl; } return 0; }
|