SPOJ MINSUB - Largest Submatrix(二分+单调栈)
Posted Shadowdsp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ MINSUB - Largest Submatrix(二分+单调栈)相关的知识,希望对你有一定的参考价值。
http://www.spoj.com/problems/MINSUB/en/
题意:给出一个n*m的矩阵M,和一个面积k,要使得M的子矩阵M\'的最小元素最大并且面积大于等于k,问子矩阵M\'的最小元素最大能是多少,并且求出最大的面积。
思路:二分一个最小元素x,转化为判断矩阵M里面是否存在一个子矩阵使得这个子矩阵的面积大于等于k并且所有元素都大于x。
用另一个矩阵,1表示该位置的元素大于等于x,0表示元素小于x。
转化为判断是否存在一个子矩阵元素为1的面积大于等于k。
这样可以用到早上学习的单调栈,去维护最大的子矩阵面积。
像这样,求出最大的矩阵面积。
如果矩阵面积大于等于k,那么就去找是否有更大的x去满足题意。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define N 1010 4 struct node { 5 int pre, suf, val; 6 } p[N]; 7 int mat[N][N], mp[N][N], h[N][N], n, m, k, square; 8 9 bool check(int x) { 10 memset(mp, 0, sizeof(mp)); 11 memset(h, 0, sizeof(h)); 12 for(int i = 1; i <= n; i++) 13 for(int j = 1; j <= m; j++) if(mat[i][j] >= x) mp[i][j] = 1; 14 square = 0; 15 for(int i = 1; i <= n; i++) { 16 stack<node> sta; 17 for(int j = 1; j <= m; j++) { 18 if(mp[i][j]) h[i][j] = h[i-1][j] + 1; 19 p[j] = (node) {1, 1, h[i][j]}; 20 } 21 sta.push(p[1]); 22 for(int j = 2; j <= m; j++) { 23 while(!sta.empty() && sta.top().val > p[j].val) { 24 node top = sta.top(); sta.pop(); 25 if(!sta.empty()) sta.top().suf += top.suf; 26 p[j].pre += top.pre; 27 square = max(square, (top.suf + top.pre - 1) * top.val); 28 } 29 sta.push(p[j]); 30 } 31 while(!sta.empty()) { 32 node top = sta.top(); sta.pop(); 33 if(!sta.empty()) sta.top().suf += top.suf; 34 square = max(square, (top.suf + top.pre - 1) * top.val); 35 } 36 } 37 if(square >= k) return true; 38 return false; 39 } 40 41 void solve() { 42 int t; 43 scanf("%d", &t); 44 while(t--) { 45 scanf("%d%d%d", &n, &m, &k); 46 int r = 0, l = 1000000000, ans; 47 for(int i = 1; i <= n; i++) { 48 for(int j = 1; j <= m; j++) { 49 scanf("%lld", &mat[i][j]); 50 if(mat[i][j] < l) l = mat[i][j]; 51 if(mat[i][j] > r) r = mat[i][j]; 52 } 53 } 54 ans = l; 55 while(l <= r) { 56 int mid = (l + r) >> 1; 57 if(check(mid)) l = mid + 1, ans = mid; 58 else r = mid - 1; 59 } 60 check(ans); 61 printf("%d %d\\n", ans, square); 62 } 63 } 64 65 int main() { 66 solve(); 67 return 0; 68 }
以上是关于SPOJ MINSUB - Largest Submatrix(二分+单调栈)的主要内容,如果未能解决你的问题,请参考以下文章
[Lintcode]184. Largest Number/[Leetcode]179. Largest Number
703. Kth Largest Element in a Stream/215. Kth Largest Element in an Array/