题目

分析

首先,设\(f_{i,j}\)表示最大的以(i,j)为左下角的正方形的边长。

转移显然,\(f_{i,j}=\max(f_{i-1,j},f_{i,j-1},f_{i-1,j-1})+1\)

接着,再设\(g_{i,j,k,l}\)表示在以\((k,l)\)为左上角,\((k+2^i-1,l+2^j-1)\)为右下角的矩阵中,最大的f。

二维rmq就不讲了。

假设询问矩阵(x,y,x1,y1),

二分答案ans(想想为什么?)



用rmq看红色区域中的最大f值是否合法。

注意:出题人将输入调的太大了,要打读入优化。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=1002;
using namespace std;
int f[N][N],n,m,T,g[11][11][N][N],a[N][N],logn,logm;
int read(int &n)
{
char ch=' ';
int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-') w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar()) q=q*10+ch-48;n=q*w;
return n;
}
int min2(int x,int y)
{
if(x>y) x=y;
return x;
}
int max2(int x,int y)
{
if(x<y) x=y;
return x;
}
int min1(int x,int y,int z)
{
if(x>y) x=y;
if(x>z) x=z;
return x;
}
int max1(int x,int y,int z,int a)
{
if(x<y) x=y;
if(x<z) x=z;
if(x<a) x=a;
return x;
}
int pref()
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(a[i][j])
g[0][0][i][j]=f[i][j]=min1(f[i-1][j-1],f[i-1][j],f[i][j-1])+1;
}
int prermq()
{
int i,j,k,l;
for(i=0;i<=logn;i++)
{ for(j=0;j<=logm;j++)
{
if(j+i!=0)
{
int p=1<<(i-1);
int q=1<<(j-1);
for(k=1;k<=n;k++)
if(k+p<=n)
{
for(l=1;l<=m;l++)
if(l+q<=m)
{
if(i!=0 && j!=0)
g[i][j][k][l]=max1(g[i-1][j-1][k][l],g[i-1][j-1][k+p][l],g[i-1][j-1][k+p][l+q],g[i-1][j-1][k][l+q]);
else
if(i==0)
g[i][j][k][l]=max2(g[i][j-1][k][l],g[i][j-1][k][l+q]);
else
if(j==0)
g[i][j][k][l]=max2(g[i-1][j][k][l],g[i-1][j][k+p][l]);
}
else break;
}
else break;
}
}
}
}
int rmq(int x,int y,int x1,int y1)
{
int p=log2(x1-x+1),q=log2(y1-y+1);
return max1(g[p][q][x][y],g[p][q][x1-(1<<p)+1][y],g[p][q][x][y1-(1<<q)+1],g[p][q][x1-(1<<p)+1][y1-(1<<q)+1]);
}
int rf(int x,int y,int x1,int y1)
{
int lx=x1-x+1,ly=y1-y+1,l=1,r=min2(lx,ly);
while(l<r-1)
{
int mid=(l+r)/2;
if(rmq(x+mid-1,y+mid-1,x1,y1)>=mid)
l=mid;
else
r=mid-1;
}
if(rmq(x+r-1,y+r-1,x1,y1)>=r)
printf("%d\n",r);
else
if(rmq(x+l-1,y+l-1,x1,y1)>=l)
printf("%d\n",l);
else
printf("0\n");
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
read(a[i][j]);
f[i][j]=a[i][j];
}
pref();
logn=log2(n);
logm=log2(m);
prermq();
scanf("%d",&T);
int x1,x2,y1,y2;
for(int i=1;i<=T;i++)
{
read(x1);
read(y1);
read(x2);
read(y2);
rf(x1,y1,x2,y2);
}
}

最新文章

  1. 解决一阻塞语句CPU直降15%
  2. js-JavaScript高级程序设计学习笔记18
  3. UVA 11992 Fast Matrix Operations(线段树:区间修改)
  4. javascript 中 typeof 的使用
  5. Tomcat7启动报Error listenerStart错误--转载
  6. spring WebServiceTemplate 调用 axis1.4 发布的webservice
  7. winform窗体间利用委托传值(一)
  8. javascript 【封装AJAX】
  9. Java线程池主线程等待子线程执行完成
  10. 【Shell Basic】Shell脚本编写规范
  11. Sping Boot入门到实战之实战篇(一):实现自定义Spring Boot Starter——阿里云消息队列服务Starter
  12. 使用sklearn时cannot import name MLPClassifier的解决办法
  13. 深入理解苹果系统(Unicode)字符串的排序方法
  14. 如何打造网站克隆、仿站工具(C#版)
  15. DHCP服务洪水攻击
  16. XenServer日志清理方法
  17. php获得可靠的精准的当前时间 ( 通过授时服务器 )
  18. 自写Jquery插件 Tab
  19. 【SpringBoot系列2】SpringBoot整合Redis
  20. Python 并发编程(管道,事件,信号量,进程池)

热门文章

  1. tmux 学习
  2. centos7 安装mongodb4.0笔记
  3. squid的三种模式
  4. redis学习(三)
  5. ios模拟器快捷键
  6. deepin之添加右键新建文档选项
  7. MyEclipse 2013 破解
  8. vue.js之过渡动画
  9. 用slot和component实现表单共用
  10. 解决IOS把数字渲染为电话号码,颜色为蓝色解决方案