Codeforces713D. Animals and Puzzle

$n<=1000,m<=1000$,$n*m$的01矩阵,给$t<=1000000$个询问,每次问一个矩形中最大的1正方形的边长。

先想想不考虑“一个矩形中”的限制,那记$f(i,j)$--以$(i,j)$为右下角的最大的正方形,那

很好,那现在加入一个边界限制,由于边长r的正方形同时也是边长r-1,r-2……的,那来二分答案吧,现在对二分的答案$x$就检查一个区域里的$f$数组中最大的那一个是否大于等于$x$。查静态区间最大,用ST表啦!拓展到二维情况即可。

 1 #include<string.h>
 2 #include<stdlib.h>
 3 #include<stdio.h>
 4 //#include<math.h>
 5 //#include<assert.h>
 6 #include<algorithm>
 7 //#include<iostream>
 8 //#include<bitset>
 9 using namespace std;
10 
11 int n,m,t;
12 #define maxn 1011
13 int a[maxn][maxn],Log[maxn];short rmq[maxn][maxn][12][12];
14 
15 int x1,x2,y1,y2;
16 int rmqquery(int x1,int y1,int x2,int y2)
17 {
18     int p=Log[x2-x1+1],q=Log[y2-y1+1];
19     return max(max(rmq[x1][y1][p][q],rmq[x2-(1<<p)+1][y1][p][q])
20     ,max(rmq[x1][y2-(1<<q)+1][p][q],rmq[x2-(1<<p)+1][y2-(1<<q)+1][p][q]));
21 }
22 bool check(int len) {return rmqquery(x1+len-1,y1+len-1,x2,y2)>=len;}
23 int main()
24 {
25     scanf("%d%d",&n,&m);
26     for (int i=1;i<=n;i++)
27         for (int j=1;j<=m;j++)
28             scanf("%d",&a[i][j]);
29     for (int i=1;i<=n;i++)
30         for (int j=1;j<=m;j++)
31             if (a[i][j]==0) rmq[i][j][0][0]=0;
32             else rmq[i][j][0][0]=min(rmq[i][j-1][0][0],min(rmq[i-1][j][0][0],rmq[i-1][j-1][0][0]))+1;
33     Log[0]=-1; for (int i=1,to=max(n,m);i<=to;i++) Log[i]=Log[i>>1]+1;
34     for (int q=1;(1<<q)<=m;q++)
35         for (int i=1;i<=n;i++)
36             for (int j=1,to=m-(1<<q)+1;j<=to;j++)
37                 rmq[i][j][0][q]=max(rmq[i][j][0][q-1],rmq[i][j+(1<<(q-1))][0][q-1]);
38     for (int p=1;(1<<p)<=n;p++)
39     {
40         for (int i=1,to=n-(1<<p)+1;i<=to;i++)
41             for (int j=1;j<=m;j++)
42                 rmq[i][j][p][0]=max(rmq[i][j][p-1][0],rmq[i+(1<<(p-1))][j][p-1][0]);
43         for (int q=1;(1<<q)<=m;q++)
44             for (int i=1,to=n-(1<<p)+1;i<=to;i++)
45                 for (int j=1,to=m-(1<<q)+1;j<=to;j++)
46                     rmq[i][j][p][q]=max(rmq[i][j][p][q-1],rmq[i][j+(1<<(q-1))][p][q-1]);
47     }
48     scanf("%d",&t);
49     while (t--)
50     {
51         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
52         int L=0,R=min(x2-x1+1,y2-y1+1);
53         while (L<R)
54         {
55             const int mid=(L+R+1)>>1;
56             if (check(mid)) L=mid;
57             else R=mid-1;
58         }
59         printf("%d
",L);
60     }
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8308328.html