Summer school more than 2019 cattle off the eighth field A All-one Matrices (+ prefix and monotonous stack)

Topic: https://ac.nowcoder.com/acm/contest/888/A

Meaning of the questions: find the number of full-1 matrix, and this matrix is not a whole other full-matrix contains 1

Ideas: The entire team pay say

-> {

  This kind of problem, the general solution is in two directions:

 

    A: one-dimensional compression, i.e., the upper and lower boundaries of the enumeration, and complexity of O (N ^ 3);

 

    B: billboard problem, i.e. the lower boundary enumeration s, s can be viewed so long as some of the tall end, disposed on the billboard and then rise, the complexity of O (N ^ 2).

}

Here we look at the complexity of the class B certainly can see, we already know how to obtain each matrix before, but how do we make sure he is not the biggest matrix extension of it, in fact, we have nothing more than to see whether the current matrix can also be extended to apply to up and down, left and right, then we've seen before dp and stack approach can find L [i], R [i], we would have is from the top down to enumerate the above extension application has not considered, we pre-out, we have to determine whether the current level is how can they branch below apply when the end of it. Are we just look at this line are all one can, then how to determine it, and judgment is equal to the prefix length of the interval, so you can, if interpreted to mean that they branch can apply, if not, the number of rectangles +1

#include<bits/stdc++.h>
#define maxn 3005
#define mod 1000000007
using namespace std;
typedef int ll;
ll n,m;
char str[maxn][maxn];
ll dp[maxn][maxn];
int vis[maxn][maxn];
ll r[maxn],l[maxn],sum[maxn];
ll cnt;
ll q[maxn],head;
void get(int t){
    head=0;q[++head]=0;
    for(int i=1;i<=m;i++){
        while(head>0&&dp[t][i]<=dp[t][q[head]]) head--;
        l[i]=q[head]+1;
        q[++head]=i;
    }  
    head=0;q[++head]=m+1;
    for(int i=m;i>=1;i--){
        while(head>0&&dp[t][i]<=dp[t][q[head]]) head--;
        r[i]=q[head]-1;
        q[++head]=i;
    }
    for(int i=1;i<=m;i++) sum[i]=sum[i-1]+(str[t+1][i]=='1');
    for(int i=1;i<=m;i++){
        if(dp[t][i]==0) continue;
        if(vis[l[i]][r[i]]==t) continue;
        if(sum[r[i]]-sum[l[i]-1]==r[i]-l[i]+1) continue;
        cnt++;
        vis[l[i]][r[i]]=t;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",str[i]+1);
    }  
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(str[i][j]=='1'){
                dp[i][j]=dp[i-1][j]+1;
            }
            else dp[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++){
        get(i);
    }
    printf("%d",cnt);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Lis-/p/11335043.html