Codeforces 713D Animals and Puzzle(二维ST表+二分答案)
题目链接 Animals and Puzzle
题意 给出一个1e3 * 1e3的01矩阵,给出t个询问,每个询问形如x1,y1,x2,y2
你需要回答在以$(x1, y1)$为左上角,$(x1, y2)$为右下角的子矩阵中,最大的全1正方形的边长。
首先考虑DP预处理。
$f[i][j]$表示以$f[i][j]$为右下角的最大的全1正方形的边长。
则$f[i][j] = min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1$
我们对$f[i][j]$构建一张二维ST表,使我们能在$O(1)$的时间复杂度内求出$f[i][j](x1 <= i <= x2, y1 <= j <= y2)$
但是这样直接查询$f[i][j]$的最大值$(x1 <= i <= x2, y1 <= j <= y2)$是不行的。
因为查询到的最大全1子正方形并不一定都在以$(x1, y1)$为左上角,$(x1, y2)$为右下角的子矩阵中。
所以我们需要另外想办法。
我们可以判断一个答案x是否存在,先求出合法的$f[i][j] >= x$的范围,
也就是说如果找到$f[i][j] >= x$了,这个找到的全1子正方形一定都在以$(x1, y1)$为左上角,$(x1, y2)$为右下角的子矩阵中。
显然x是单调的,所以我们可以二分答案。
时间复杂度$O(nmlognm + t)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 1e3 + 3;
const int M = 10; int f[N][N][M][M], lg[N];
int n, m, x, q; void ST(){
rep(i, 2, 1e3 + 1) lg[i] = lg[i >> 1] + 1;
rep(i, 1, n){
for (int k = 1; (1 << k) <= m; ++k){
rep(j, 1, m - (1 << k) + 1){
f[i][j][0][k] = max(f[i][j][0][k - 1], f[i][j + (1 << (k - 1))][0][k - 1]);
}
}
} for (int k1 = 1; (1 << k1) <= n; ++k1){
rep(i, 1, n - (1 << k1) + 1){
for (int k2 = 0; (1 << k2) <= m; ++k2){
rep(j, 1, m - (1 << k2) + 1){
f[i][j][k1][k2] = max(f[i][j][k1 - 1][k2], f[i + (1 << (k1 - 1))][j][k1 - 1][k2]);
}
}
}
}
} int query(int x1, int y1, int x2, int y2){
int k1 = lg[x2 - x1 + 1], k2 = lg[y2 - y1 + 1];
x2 = x2 - (1 << k1) + 1;
y2 = y2 - (1 << k2) + 1;
return max(max(f[x1][y1][k1][k2], f[x1][y2][k1][k2]), max(f[x2][y1][k1][k2], f[x2][y2][k1][k2]));
} int main(){ freopen("1.txt", "r", stdin);
freopen("2.txt", "w", stdout); scanf("%d%d", &n, &m); rep(i, 1, n){
rep(j, 1, m){
int x;
scanf("%d", &x);
if (x) f[i][j][0][0] = min(f[i - 1][j - 1][0][0],
min(f[i - 1][j][0][0], f[i][j - 1][0][0])) + 1;
else f[i][j][0][0] = 0;
}
} ST();
scanf("%d", &q);
while (q--){
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int l = 0, r = min(x2 - x1, y2 - y1) + 1, ans = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (query(x1 + mid - 1, y1 + mid - 1, x2, y2) >= mid) l = mid + 1, ans = mid;
else r = mid - 1;
} printf("%d\n", ans);
} return 0;
}
Codeforces 713D Animals and Puzzle(二维ST表+二分答案)的更多相关文章
- Codeforces Round #371 (Div. 1) D - Animals and Puzzle 二维ST表 + 二分
D - Animals and Puzzle #include<bits/stdc++.h> #define LL long long #define fi first #define s ...
- 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表
[题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...
- BZOJ3577:玩手机(最大流,二维ST表)
Description 现在有一堆手机放在坐标网格里面(坐标从1开始),坐标(i,j)的格子有s_(i,j)个手机. 玩手机当然需要有信号,不过这里的手机与基站与我们不太一样.基站分为两种:发送站和接 ...
- BZOJ1047[HAOI2007]理想的正方形——二维ST表
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...
- 【洛谷 P2216】 [HAOI2007]理想的正方形(二维ST表)
题目链接 做出二维\(ST\)表,然后\(O(n^2)\)扫一遍就好了. #include <cstdio> #include <cstring> #include <a ...
- [模板]二维ST表
考试yy二维ST表失败导致爆零. 其实和一维的ST表很像... 也是设$f[i][j][p][q]$为以$(i, j)$为左上角,长为$2^p$,宽为$2^q$的矩形的最大值. 算法流程是先把每一行都 ...
- [HNOI2007] 理想正方形 二维ST表
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至 ...
- Codeforces Round #371 (Div. 1) D. Animals and Puzzle 二维倍增
D. Animals and Puzzle 题目连接: http://codeforces.com/contest/713/problem/D Description Owl Sonya gave a ...
- [总结] 二维ST表及其优化
二维 \(\mathcal{ST}\) 表,可以解决二维 \(\mathcal{RMQ}\) 问题.这里不能带修改,如果要修改,就需要二维线段树解决了. 上一道例题吧 ZOJ2859 类比一维 \(\ ...
随机推荐
- Linux之centos7 VMware安装教程
Linux系统安装 下面是centOS7的安装过程 VMware 系统搭建 1 新建虚拟机 2 选择自定义 3 选择稍后安装操作系统 4 选择操作系统的版本Linux centos64位 5 选择处理 ...
- java web.xml被文件加载过程及加载顺序小结
web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...
- tp5 -- 微信公众号支付
近来期间比较忙, 忙完之后发现最近有挺多的东西没有整理,于是乎.就将以前用到的一些小东西整理了一下. 如果对您有帮助,则是我最大的幸运. 本篇主要是说了一下整合TP5的微信公众号支付. 不过由于最近T ...
- [CODEVS] 2189 数字三角形W
数字三角形 要求走到最后mod 100最大 可达性DP(好像是这样叫) 用bool数组f[i][j][k]表示 位置(i,j)能否得到k(mod 100意义下) 转移条件 f[i][j][k]=f[i ...
- 下载PhantomJS
PhantomJS新手?阅读并学习快速入门指南. 视窗 下载phantomjs-2.1.1-windows.zip(17.4 MB)并解压缩(解压缩)内容. 可执行文件phantomjs.exe已准备 ...
- break、continue、exit、return的区别和对比
break.continue.exit.return的区别和对比 一:说明 break.continue在条件循环语句及循环语句(for.while.if等)中用于控制程序的走向:而exit则用于种植 ...
- 老男孩Python高级全栈开发工程师【真正的全套完整无加密】
点击了解更多Python课程>>> 老男孩Python高级全栈开发工程师[真正的全套完整无加密] 课程大纲 老男孩python全栈,Python 全栈,Python教程,Django ...
- laravel中对加载进行优化
在laravel中的模型与模型之间创建好关联关系会比较方便的方法 但是我们为了方便,有时也会忽略一些东西,比如: 我们在控制器中把整个一个文章对象传到了模板页面 在一次for循环下, 我们对数据进行了 ...
- JavaScript正则表达式-重复次数(数量词)
*:表示对前面表达式的匹配出现零次或多次. var reg_pattern = /bo*/;//匹配b.bo.boooo +:表示对前面表达式的匹配连续出现一次或多次. var reg_pattern ...
- win7定时关机
菜单>附件>系统工具>任务计划程序>创建基本任务 alt+r>cmd>shutdown/? 查看相关参数 /l 注销 /s 关机 /r 重启 /g 重启,重启后,重 ...