2019牛客暑期多校訓練營(第八場)A All-one Matrices 動態規劃

題意:問你全是1的子矩陣有多少個,要求不重複也不被包含

題解:跟上次的次大子矩陣差不多,都是利用單調棧或動態規劃求左右邊界解決問題,但這次問題有點變動,因爲要去重。

首先對於每個點都有一個左右邊界,那麼同一行的左右邊界相同的一定是相同的矩陣,這裏我用的set去重

同一列左右邊界相同的是子矩陣,只需要判一下與相鄰的下一行,如果一樣也得去掉

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e3+5, INF = 0x3f3f3f3f;
#define mod int(1e9+7)
#define pi acos(-1.0)
int n,m;
char a[maxn][maxn];int l[maxn],r[maxn];
int h[maxn][maxn];
struct Node {
    int l,r;
    bool operator ==(const Node &rhs)const {
        if(l==rhs.l&&r==rhs.r)return 1;
        else return 0;
    }
    bool operator <(const Node &rhs)const {
        if(l==rhs.l)return r<rhs.r;
        return l<rhs.l;
    }
}ans[maxn][maxn];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]=='1')h[i][j]=h[i-1][j]+1;
            else h[i][j]=0;
        }
    }
    //ll ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            l[j]=r[j]=j;
        }
        h[i][0]=-1;h[i][m+1]=-1;
        l[0]=1;l[m+1]=m;
        for(int j=1;j<=m;j++){
            while(h[i][j]<=h[i][l[j]-1]){
                l[j]=l[l[j]-1];
            }
        }
        for(int j=m;j>=1;j--){
            while(h[i][j]<=h[i][r[j]+1]){
                r[j]=r[r[j]+1];
            }
        }
        //set<Node>v;
        for(int j=1;j<=m;j++){
            ans[i][j].l=l[j],ans[i][j].r=r[j]; 
        }
    }
    ll res=0;
    for(int i=1;i<=n;i++){
        set<Node>v;
        for(int j=1;j<=m;j++){
            if(a[i][j]!='1')continue;
            if(i<=n-1&&ans[i][j].l==ans[i+1][j].l&&ans[i][j].r==ans[i+1][j].r)continue;
            Node tmp;tmp.l=ans[i][j].l;tmp.r=ans[i][j].r;
            v.insert(tmp);
            //if(i==4)cout<<tmp.l<<" "<<tmp.r<<endl;
        }
        //if(i==4)cout<<v.size()<<endl;
        res+=v.size();
    }
    printf("%lld\n",res);
}
/*
3 4
0111
1110
0101
3 3
111
010
111
5
4 4
1111
1011
1111
1111
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章