SPOJ_MINSUB:Largest_Submatrix(二分+单调栈)
来源:互联网 发布:守望先锋先锋大神数据 编辑:程序博客网 时间:2024/05/28 11:49
题目大意是说给定一个R*C的非负矩阵,试求出一个包含数字数>=K的子矩阵,使得这个子矩阵中最小的数字最大.
解题思路主要是二分答案,即二分那个最小的数字,然后针对每次二分的值mid,可以将原矩阵根据是否满足A[i][j]>=mid,而转成一个R*C的01矩阵a[][],然后问题求变成了给定一个二维01矩阵,求最大的满1矩阵,可以用单调栈的思想来处理这个子问题,设b[i][j]表示从a[i][j]的位置(包含)向上最多有几个连续的1存在
比如 1 1 0
1 0 1
的b[][]={{1,1,0},{2,0,1}}
然后对于每个i单独处理第i行(即子矩阵是以第i行为下边界的情况),设lef[i][j]表示从j开始向左满足b[i][k]>=b[i][j]条件所能延伸到的最大的位置,而rig[i][j]类似表示相应能够到的最右的位置
比如 j=1 2 3 4 5 6
b[][j]=4 1 3 2 5 6
则lef[][]=1 1 3 3 5 6
rig[][]=1 6 3 6 6 6
解题思路主要是二分答案,即二分那个最小的数字,然后针对每次二分的值mid,可以将原矩阵根据是否满足A[i][j]>=mid,而转成一个R*C的01矩阵a[][],然后问题求变成了给定一个二维01矩阵,求最大的满1矩阵,可以用单调栈的思想来处理这个子问题,设b[i][j]表示从a[i][j]的位置(包含)向上最多有几个连续的1存在
比如 1 1 0
1 0 1
的b[][]={{1,1,0},{2,0,1}}
然后对于每个i单独处理第i行(即子矩阵是以第i行为下边界的情况),设lef[i][j]表示从j开始向左满足b[i][k]>=b[i][j]条件所能延伸到的最大的位置,而rig[i][j]类似表示相应能够到的最右的位置
比如 j=1 2 3 4 5 6
b[][j]=4 1 3 2 5 6
则lef[][]=1 1 3 3 5 6
rig[][]=1 6 3 6 6 6
然后求lef[][]和rig[][]的过程对于每行可以运用单调栈在O(n)时限内完成,然后这样一次验证的时间复杂度是O(n^2),算上外层的二分过程,总体复杂度为O(N^2*logN),可以通过此题.
#include<iostream>#include<stdio.h>#include<string.h>#include<stdlib.h>using namespace std;const int N=2008;#define maxx(x,y) (((x)>(y))?(x):(y))int n,m,tar,a[N][N],b[N][N],lef[N][N],rig[N][N],d[N],ans;int read(void){char c=getchar();while(c<'0'||c>'9')c=getchar();int t=c-48;for(c=getchar();c>='0'&&c<='9';c=getchar())t=(t<<1)+(t<<3)+c-48;return t;}int pan(int x){int i,j,ans;ans=0;for(j=1;j<=m;j++)b[1][j]=(a[1][j]>=x);for(i=2;i<=n;i++)for(j=1;j<=m;j++)b[i][j]=(a[i][j]>=x)?(1+b[i-1][j]):0;for(i=1;i<=n;i++){d[d[0]=1]=lef[i][1]=1;for(j=2;j<=m;j++){while(d[0]>0&&b[i][d[d[0]]]>=b[i][j])d[0]--;lef[i][j]=(d[0])?(d[d[0]]+1):1;d[++d[0]]=j;}d[d[0]=1]=rig[i][m]=m;for(j=m-1;j>=1;j--){while(d[0]>0&&b[i][d[d[0]]]>=b[i][j])d[0]--;rig[i][j]=(d[0])?(d[d[0]]-1):m;d[++d[0]]=j;}for(j=1;j<=m;j++)if(b[i][j])ans=maxx(ans,b[i][j]*(rig[i][j]-lef[i][j]+1));}return (ans>=tar)?ans:0;}int main(void){int i,j,t,left,right,mid;t=read();while(t--){ans=0;n=read();m=read();tar=read();for(i=1;i<=n;i++)for(j=1;j<=m;j++)a[i][j]=read();left=0;right=1000000000;while(left+1<right){mid=(left+right)>>1;if(pan(mid))left=mid;else right=mid-1;}if(pan(right))left=right;printf("%d %d\n",left,pan(left));}return 0;}
0 0
- SPOJ_MINSUB:Largest_Submatrix(二分+单调栈)
- SPOJ_MINSUB:Largest_Submatrix(二分+单调栈)
- 二分+单调栈 SPOJ MINSUB
- SPOJ MINSUB 二分+单调栈
- poj 2796 st算法+二分 / 单调栈
- SPOJ MINSUN Largest Submatrix [二分+单调栈]
- 【二分\单调队列】绿色通道
- 二分查找单调队列
- HDOJ 4362 —— DP + 二分 | 单调栈
- 诺诺的队列(单调栈的第一次运用+二分)
- [HDU 5875] Function (单调栈/(RMQ+二分))
- [BZOJ1414][ZJOI2009]对称的正方形(manacher+单调栈+二分)
- SPOJ-MINSUB - Largest Submatrix(单调栈,二分,好题)
- 【单调栈 二分+BFS】【POI2006】ZAB-Frogs BZOJ1514
- [BZOJ4237]稻草人(cdq分治+单调栈+二分)
- 1012: [JSOI2008]最大数maxnumber 单调栈+二分
- bzoj1012 [JSOI2008]最大数(单调栈+二分/线段树)
- BZOJ4237:稻草人 (CDQ分治+二分+单调栈)
- 如何实现浏览器内多个标签页之间的通信
- 史上最全的maven pom.xml文件教程详解
- java-synchronized 嵌套使用
- 使用WebService实现远程调用
- 异步请求和超时控制
- SPOJ_MINSUB:Largest_Submatrix(二分+单调栈)
- 系统默认安装路径修改方法
- FanChat学习笔记(一)——MVP模式的应用
- Redis Sentinel机制与用法(一)
- Flask学习总结笔记(6) -- Flask-Moment本地化日期和时间
- SpringMVC上传、解析Excel
- UGUI对话框自适应
- 控制台在指定位置画矩形,写字符串,画直线
- java transient关键字