JZOJ3672] [] [JSOI2014 puzzle (puzzle)

Subject to the effect

A \ (n * m \) of the matrix 01 cut along the column several times, split into a number of \ (n * w_i \) the size of the matrix, you can re-arrange them to any makes up a new \ (n * m \) of the matrix 01, so that the maximum all-zero matrix largest rectangle.

Solution

This title key is \ (n-m * \ ^ 5 Leq 10 \) , i.e. the matrix size does not exceed \ (10 ^ 5 \) . An intuitive planning balance, i.e. points \ (n \ leq \ sqrt { 10 ^ 5} \) and \ (m \ leq \ sqrt { 10 ^ 5} \) two cases design algorithms.

  • \ (N \ leq \ sqrt {10 ^ 5} \)

Final full enumeration of the upper and lower boundary rectangle 0 \ (L, R & lt \) , and then classifies each submatrix. If the matrix of small \ (L \) -th row to \ (R & lt \) row is all zero, is divided into Class I, Class II or divided.

Finally, I must be the class of matrix in the middle, both sides put a matrix class II to make up an all-0 rectangle, then we need to calculate the matrix width and class I and class II on the left as a matrix up to a few all-0 right up to a few as all zeros. Note that, about not using the same class II matrix, so we have a record next big value, replace it with the second largest maximum value can not be used.

Time complexity \ (O (n-2M ^) = O (10 ^ 5N) \) , \ (n-\) is the root level, apparently does not time out.

  • \ (M \ leq 10 ^ 5 \)

Then we can not directly upper and lower boundaries of the rectangle enumeration, we can use another method to enumerate the upper and lower boundaries:

Each point record rectangle \ ((i, j) \ ) up the first \ (1 \) line number (referred to as \ (up [I] [J] \) ). Each point enumeration rectangle \ ((I, J) \) , the \ (up [i] [j ] \) as the upper boundary, \ (I \) as the lower boundary. (Replacing the original enumeration of violence on the border \ (r \) , the lower boundary \ (L \) )

The remaining process above can be applied, the time complexity \ (O (nm ^ 2) = 10 ^ 5m O () \) , \ (m \) is the root level, it will not time out.

So far, the problem is solved.

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=100007;

int T;
int s,n,m,ans,w[N],st[N],en[N],sum[N],a[N],up[N];

int id(int x,int y){
    if(x<1||y<1)return 0;
    return (y-1)*n+x;
}
int get(int x1,int x2,int y1,int y2){
    return sum[id(x2,y2)]-sum[id(x1-1,y2)]-sum[id(x2,y1-1)]+sum[id(x1-1,y1-1)];
}

void calc(int l,int r){
    for(int i=1;i<=s;++i)for(int j=st[i],ret=0;j<=en[i];++j){
        if(get(l,r,j,j)==0)++ret;
        else ret=0;
        ans=max(ans,(r-l+1)*ret);
    }
    int L[2][2],R[2][2],mid=0;
    memset(L,0,sizeof(L));
    memset(R,0,sizeof(R));
    for(int i=1;i<=s;++i){
        int mxl=0,mxr=0;
        for(int j=st[i];j<=en[i];++j)if(get(l,r,j,j)==0)++mxl;else break;
        for(int j=en[i];j>=st[i];--j)if(get(l,r,j,j)==0)++mxr;else break;
        if(mxl==w[i])mid+=w[i];
        else{
            if(mxl>L[0][0])L[0][0]=mxl,L[0][1]=i;
            else if(mxl>L[1][0])L[1][0]=mxl,L[1][1]=i;
            if(mxr>R[0][0])R[0][0]=mxr,R[0][1]=i;
            else if(mxr>R[1][0])R[1][0]=mxr,R[1][1]=i;
        }
    }
    for(int p=0;p<2;++p)for(int q=0;q<2;++q)if(L[p][1]!=R[q][1])ans=max(ans,(r-l+1)*(mid+L[p][0]+R[q][0]));
    ans=max(ans,(r-l+1)*(mid+L[0][0]));
    ans=max(ans,(r-l+1)*(mid+R[0][0]));
}

int main(){
    scanf("%d",&T);
    while(T--){
        m=ans=0;
        scanf("%d%d",&s,&n);
        memset(w,0,sizeof(w));
        memset(st,0,sizeof(st));
        memset(en,0,sizeof(en));
        memset(sum,0,sizeof(sum));
        memset(a,0,sizeof(a));
        memset(up,0,sizeof(up));
        for(int i=1;i<=s;++i){
            scanf("%d",&w[i]);
            st[i]=m+1;
            for(int j=1;j<=n;++j)for(int k=1;k<=w[i];++k){
                char c;scanf(" %c",&c);
                a[id(j,m+k)]=c-'0';
            }
            m+=w[i],en[i]=m;
        }
        for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)sum[id(i,j)]=sum[id(i-1,j)]+sum[id(i,j-1)]-sum[id(i-1,j-1)]+a[id(i,j)];
        for(int j=1;j<=m;++j)
            for(int i=1,lst=0;i<=n+1;++i)
                if(i>n||a[id(i,j)]){
                    for(int k=lst+1;k<=i-1;++k)up[id(k,j)]=i-1;
                    lst=i;
                }
        if(n<m)for(int i=1;i<=n;++i)for(int j=i;j<=n;++j)calc(i,j);
        else for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)calc(i,up[id(i,j)]);
        printf("%d\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zjlcnblogs/p/12040171.html