[caioj]单调队列3 单调队列
2017-08-04 08:51
288 查看
【题意】
给一个N*M的数矩阵
现在求一个子矩阵 要求子矩阵中最大值与最小值的差<=C。而且子矩阵的宽度(横)不超过100(长(竖)没有限制)。 求子矩阵的最大面积。
【输入格式】
第一行两个整数 M(左右方向),N(上下方向)和 C (N,M<=500 0<=C<= 10 )
接下来 N行 每行M个数 每个数(-30000~30000)
【输出格式】
子矩阵的最大面积
【样例输入】
10 15 4
41 40 41 38 39 39 40 42 40 40
39 40 43 40 36 37 35 39 42 42
44 41 39 40 38 40 41 38 35 37
38 38 33 39 36 37 32 36 38 40
39 40 39 39 39 40 40 41 43 41
39 40 41 38 39 38 39 39 39 42
36 39 39 39 39 40 39 41 40 41
31 37 36 41 41 40 39 41 40 40
40 40 40 42 41 40 39 39 39 39
42 40 44 40 38 40 39 39 37 41
41 41 40 39 39 40 41 40 39 40
47 45 49 43 43 41 41 40 39 42
42 41 41 39 40 39 42 40 42 42
41 44 49 43 46 41 42 41 42 42
45 40 42 42 46 42 44 40 42 41
【样例输出】
35
给一个N*M的数矩阵
现在求一个子矩阵 要求子矩阵中最大值与最小值的差<=C。而且子矩阵的宽度(横)不超过100(长(竖)没有限制)。 求子矩阵的最大面积。
【输入格式】
第一行两个整数 M(左右方向),N(上下方向)和 C (N,M<=500 0<=C<= 10 )
接下来 N行 每行M个数 每个数(-30000~30000)
【输出格式】
子矩阵的最大面积
【样例输入】
10 15 4
41 40 41 38 39 39 40 42 40 40
39 40 43 40 36 37 35 39 42 42
44 41 39 40 38 40 41 38 35 37
38 38 33 39 36 37 32 36 38 40
39 40 39 39 39 40 40 41 43 41
39 40 41 38 39 38 39 39 39 42
36 39 39 39 39 40 39 41 40 41
31 37 36 41 41 40 39 41 40 40
40 40 40 42 41 40 39 39 39 39
42 40 44 40 38 40 39 39 37 41
41 41 40 39 39 40 41 40 39 40
47 45 49 43 43 41 41 40 39 42
42 41 41 39 40 39 42 40 42 42
41 44 49 43 46 41 42 41 42 42
45 40 42 42 46 42 44 40 42 41
【样例输出】
35
题解:
我的方法复杂度似乎是对的,但被卡了1个点?我太菜了……我的方法是先预处理出mx[i][j][k]和mn[i][j][k],分别表示第i行第j列的数数起k个数中的最大最小值,然后枚举列的起点j与跨度k,然后用一个单调队列维护最多能延伸多少行,时间复杂度为O(100∗n∗m)。然而我还是被卡。代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=505; int m,n,c,a[maxn][maxn],start[maxn]; int mx[maxn][maxn][105]; int mn[maxn][maxn][105]; bool mark[maxn]; struct Queue{int mx,mn;}q[maxn]; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int main() { // freopen("airport9.in","r",stdin); m=read();n=read();c=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),mx[i][j][1]=mn[i][j][1]=a[i][j]; for(int k=2;k<=min(m,35);k++) for(int i=1;i<=n;i++) for(int j=1;j+k-1<=m;j++) mx[i][j][k]=max(mx[i][j][k-1],a[i][j+k-1]), mn[i][j][k]=min(mn[i][j][k-1],a[i][j+k-1]); int ans=1; q[0].mx=-999999999; q[0].mn=999999999; for(int i=1;i<=m;i++)start[i]=1; for(int k=1;k<=min(m,35);k++) { for(int j=1;j+k-1<=m;j++) { if(mark[j])continue; int head=1,tail=1,i; for(i=start[j];i<=n;i++) if(mx[i][j][k]-mn[i][j][k]<=c)break; if(i==n+1){mark[j]=true;continue;} start[j]=i; if(mx[i][j][k]-mn[i][j][k]<=c) { q[1].mx=mx[i][j][k];q[1].mn=mn[i][j][k]; ans=max(ans,k); for(int l=i+1;l<=n;l++) { if(mx[l][j][k]-mn[l][j][k]>c) { if((n-l)*k<=ans)break; head=1;tail=0;continue; } while(head<=tail&&max(mx[l][j][k],q[head].mx)-min(mn[l][j][k],q[head].mn)>c) { head++; q[head].mx=max(q[head].mx,q[head-1].mx); q[head].mn=min(q[head].mn,q[head-1].mn); } if(head<=tail)ans=max(ans,k*(tail-head+2)); tail++; q[tail].mx=mx[l][j][k]; q[tail].mn=mn[l][j][k]; q[head].mx=max(q[head].mx,q[tail].mx); q[head].mn=min(q[head].mn,q[tail].mn); } } } } printf("%d\n",ans); }
相关文章推荐
- [caioj]单调队列3 单调队列
- 【算法学习笔记】53.单调队列的简单应用 SJTU OJ 1034 二哥的金链
- 哈理工oj(acm.hrbust.edu.cn) 1522【单调队列】
- 单调队列(oj1771)
- Assignment ZQOJ 25691 单调队列
- 哈理工OJ 1522 子序列的和(单调队列)(dp)
- 交大OJ 1069 二哥的硬币(多重背包/单调队列)
- hdu3530——Subsequence(单调队列优化DP)
- 【单调队列】【3-21个人赛】【problmeB】
- POJ 3017 Cut the Sequence (单调队列优化DP)
- Bad Hair Day--(单调队列)
- POJ 2823 Sliding Window(单调队列)
- hdu 2430 Beans 单调队列
- POJ 2823 Sliding Window(单调队列)
- 暑假集训日记--8.14--单调队列
- POJ 2823 单调队列
- 单调队列的应用
- ACM-单调队列用于DP优化
- POJ 2823 Sliding Window 单调队列
- FZU 1894 志愿者选拔 单调队列