zoukankan      html  css  js  c++  java
  • 2019牛客多校训练第八场A.All-one Matrices(前缀和+单调栈)

    题目传送门

    题意:

    输入n和m,给出一个n行m列的01矩阵,求出所有的不可扩大的全1矩阵个数。

    题解:

    预处理每个格子的高度up[i][j](其向上连续的1的个数),枚举每一行 i,维护单调栈(单调上升)求每个格子 j 以up[i][j]为高可达到的全1矩阵左边界pos和右边界j,此时得到的全1矩阵不能再向上左右拓展,只要判断能否再向下拓展即可。只要下一行[pos,j]区间内有0存在,即该全1矩阵不能向下拓展。

    维护单调栈时,当前点高度等于栈顶元素高度,则说明是重复的,不用计算。

    Code:

    手写栈:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=3005;
     4 int a[maxn][maxn],sum[maxn][maxn],up[maxn][maxn],height[maxn],sta[maxn];
     5 int main()
     6 {
     7     int n,m;
     8     scanf("%d%d",&n,&m);
     9     for(int i=1;i<=n;i++){
    10         for(int j=1;j<=m;j++){
    11             scanf("%1d",&a[i][j]);
    12             up[i][j]=(a[i][j]==1)?up[i-1][j]+1:0;//预处理每个格子(i,j)向上的连续的1的个数
    13             sum[i][j]=sum[i][j-1]+a[i][j];//预处理每行的前缀和,方便判断矩形能否向下拓展
    14         }
    15     }
    16     int ans=0;
    17     for(int i=1;i<=n;i++){
    18         int top=0;
    19         for(int j=1;j<=m+1;j++){
    20             int pos=j;
    21             while(top&&up[i][j]<height[top]){ 
    22                 if(i==n||(sum[i+1][j-1]-sum[i+1][sta[top]-1])<j-sta[top])//不可向下拓展,答案+1
    23                     ans++;
    24                 pos=sta[top];//向左最远能拓展的位置pos
    25                 top--; //出栈
    26             }
    27             if(up[i][j]&&(!top||up[i][j]>height[top])) //入栈
    28                 height[++top]=up[i][j],sta[top]=pos;
    29         }
    30     }
    31     printf("%d
    ",ans);
    32     return 0;
    33 }

    STL的stack:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=3005;
     5 int a[maxn][maxn],up[maxn][maxn];
     6 int main()
     7 {
     8     int n,m;
     9     scanf("%d%d",&n,&m);
    10     for(int i=1;i<=n;i++){
    11         for(int j=1;j<=m;j++){
    12             scanf("%1d",&a[i][j]);
    13             up[i][j]=(a[i][j]==1)?up[i-1][j]+1:0;
    14         }
    15     }
    16     int ans=0;
    17     for(int i=1;i<=n;i++){
    18         int temp=0;
    19         stack<pair<int,int> >S;
    20         for(int j=1;j<=m+1;j++){
    21             int pos=j;
    22             while(!S.empty()&&up[i][j]<S.top().first){
    23                 if(S.top().second<=temp)//下一行[pos,j]中有0存在,故不可向下扩展,答案+1
    24                     ans++;
    25                 pos=S.top().second;
    26                 S.pop();
    27             }
    28             if(!up[i+1][j])temp=j;//记录下一行中截至当前最右边0的位置
    29             if(S.empty()||up[i][j]>S.top().first)
    30                 S.push({up[i][j],pos});
    31         }
    32     }
    33     printf("%d
    ",ans);
    34     return 0;
    35 }
  • 相关阅读:
    linux 查看安装软件位置(持续跟新)
    POJ 3661 Running (DP思想)
    stringstream的用法
    关于实验室搬家
    POJ 搜索(2)
    Treap的插入删除实现
    碰到一道不错的扩展欧几里德题目 whu 1338
    SRM 144
    关于无向图双连通问题
    POJ 动态规划(2)
  • 原文地址:https://www.cnblogs.com/HOLLAY/p/11350856.html
Copyright © 2011-2022 走看看