Codeforces Round 371 D Animals and Puzzle

来源:互联网 发布:网络任务源码 编辑:程序博客网 时间:2024/06/03 12:34

Task:
给你一张01图,以及t个询问,每个询问为(x1,y1,x2,y2),指在以(x1,y1)为左下角,以(x2,y2)为右下角的矩形中,最大的全为1的矩形的大小.

Sample Input
3 4
1 1 0 1
0 1 1 0
0 1 1 0
5
1 1 2 3
2 1 3 2
3 2 3 4
1 1 3 4
1 2 3 4

Sample Output
1
1
1
2
2

Solution:
这道题目首先我们先O(n2)地处理出以每个点为右下角,组成的矩形最大为多大.
然后对于每个询问,我们先去二分一个答案,然后再在(x1+x,y1+x,x2,y2)中搜一个最大值,如果这个最大值大于x,继续搜比x大的,反之,则搜比x小的.
而求这个最大值,我们可以用二维的st表,St_Table[i][j][k][l]表示以(i,j)为左下角,向右2k,向上2l,这个矩形中的最大值.
而求一个(x1,y1,x2,y2)的矩形的最大值就是

max(StTable[x1][y1][log2x2x1][log2y2y1],
StTable[x1][y22log2y2y1][log2x2x1][log2y2y1],
StTable[x22log2x2x1][y1][log2x2x1][log2y2y1],
StTable[x22log2x2x1][y22log2y2y1][log2x2x1][log2y2y1])

这样就能够A了.

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 1001#define LOGM 11using namespace std;int mp[M][M],dp[M][M];int St_Table[M][M][LOGM][LOGM];int Pow[28],Log[M];int query(int x,int nx,int y,int ny){    if(ny<y)return 0;    int lenx=nx-x+1,leny=ny-y+1;    int Lgy=Log[leny],Lgx=Log[lenx];    int xMx=max(St_Table[x][y][Lgx][Lgy],St_Table[x][ny-Pow[Lgy]+1][Lgx][Lgy]);    int yMx=max(St_Table[nx-Pow[Lgx]+1][y][Lgx][Lgy],St_Table[nx-Pow[Lgx]+1][ny-Pow[Lgy]+1][Lgx][Lgy]);    return max(xMx,yMx);}int main(){    int n,m;    scanf("%d %d",&n,&m);    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            scanf("%d",&mp[i][j]);    for(int i=1;i<=n;i++)dp[i][1]=mp[i][1];    for(int i=1;i<=m;i++)dp[1][i]=mp[1][i];    for(int i=2;i<=n;i++)        for(int j=2;j<=m;j++)            if(mp[i][j])dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;            else dp[i][j]=0;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            St_Table[i][j][0][0]=dp[i][j];    int rs=0;    Pow[0]=1;    for(int i=1;i<28;i++)Pow[i]=Pow[i-1]<<1;    Log[0]=-1;    for(int i=1;i<M;i++)Log[i]=Log[i>>1]+1;    for(int l=0;l+1<LOGM;l++)        for(int k=0;k+1<LOGM;k++)            for(int i=1;i<=n-Pow[l]+1;i++)                for(int j=1;j<=m-Pow[k]+1;j++){                    int Mj=j+Pow[k],Mi=i+Pow[l];;                    St_Table[i][j][l][k+1]=max(St_Table[i][j][l][k],St_Table[i][Mj][l][k]);                    St_Table[i][j][l+1][k]=max(St_Table[i][j][l][k],St_Table[Mi][j][l][k]);                }    int cas,x1,x2,y1,y2;    scanf("%d",&cas);    while(cas--&&scanf("%d %d %d %d",&x1,&y1,&x2,&y2)!=EOF){        int ans=0;        int L=0,R=min(x2-x1+1,y2-y1+1);        while(L<=R){            int mid=L+R>>1;            if(query(x1+mid-1,x2,y1+mid-1,y2)>=mid)ans=mid,L=mid+1;            else R=mid-1;        }        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击