题面

动态加障碍物,同时查询最大子正方形。

n,m≤2000n,m\leq2000n,m≤2000

题解

加障碍不好做,直接离线后反着做,每次就是清除一个障碍物。

显然倒着做答案是递增的,而且答案的值域是[0,min⁡(n,m)][0,\min(n,m)][0,min(n,m)],所以我们可以存一下答案,然后每次checkcheckcheck能不能+1+1+1。

考虑把一个位置的障碍物清除后如果答案能变大,这个矩阵一定包含这个位置。那么考虑怎么求是否存在一个边长为lenlenlen的矩形覆盖这个位置。

我们存下l[i][j]l[i][j]l[i][j]和r[i][j]r[i][j]r[i][j],表示(i,j)(i,j)(i,j)位置向左和向右最多能扩展的距离。这个东西是可以维护的,因为每次改一个点只会影响一行mmm个数的值。直接暴力修改。

然后对于(i,j)(i,j)(i,j)位置,如果存在一个边长为lenlenlen的正方形覆盖(i,j)(i,j)(i,j),一定在第jjj列存在连续lenlenlen行满足:

min⁡(l[k][j])+min⁡(r[k][j])−1≥len\min(l[k][j])+\min(r[k][j])-1\geq lenmin(l[k][j])+min(r[k][j])−1≥len

这样我们就可以直接two-pointers,两个单调队列维护lll和rrr的最小值来判断是否存在答案。

我的代码中并没有保证一定经过(i,j)(i,j)(i,j)这个点,但是这样并不会错过答案。

时间复杂度O(nm)O(nm)O(nm)

CODE

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2005;
int n, m, k, l[MAXN][MAXN], r[MAXN][MAXN];
char S[MAXN];
int a[MAXN][MAXN], dp[MAXN][MAXN], x[MAXN], y[MAXN], ans[MAXN];
void clr(int i) {
for(int j = 1; j <= m; ++j) l[i][j] = a[i][j] ? 0 : l[i][j-1] + 1;
for(int j = m; j >= 1; --j) r[i][j] = a[i][j] ? 0 : r[i][j+1] + 1;
}
int solve() {
int re = 0;
for(int i = 1; i <= n; ++i) clr(i);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(!a[i][j]) {
dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
re = max(re, dp[i][j]);
}
return re;
} int v[2][MAXN], q[2][MAXN], s[2], t[2];
inline void del(int p) {
while(s[0] < t[0] && q[0][s[0]] <= p) ++s[0];
while(s[1] < t[1] && q[1][s[1]] <= p) ++s[1];
}
inline void ins(int i) {
while(s[0] < t[0] && v[0][q[0][t[0]-1]] >= v[0][i]) --t[0]; q[0][t[0]++] = i;
while(s[1] < t[1] && v[1][q[1][t[1]-1]] >= v[1][i]) --t[1]; q[1][t[1]++] = i;
}
bool calc(int j, int len) {
for(int i = 1; i <= n; ++i) v[0][i] = l[i][j], v[1][i] = r[i][j];
s[0] = s[1] = t[0] = t[1] = 0;
q[0][0] = q[1][0] = 0;
for(int i = 1, p = 0; i <= n; ++i) {
while(i-p >= len) del(p++); ins(i);
if(i >= len && v[0][q[0][s[0]]] + v[1][q[1][s[1]]] - 1 >= len) return 1;
}
return 0;
}
int main () {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i) {
scanf("%s", S+1);
for(int j = 1; j <= m; ++j)
a[i][j] = S[j] == 'X';
}
for(int i = 1; i <= k; ++i) scanf("%d%d", &x[i], &y[i]), a[x[i]][y[i]] = 1;
ans[k] = solve();
for(int i = k; i > 1; --i) {
a[x[i]][y[i]] = 0;
clr(x[i]);
for(ans[i-1]=ans[i]; calc(y[i], ans[i-1]+1); ++ans[i-1]);
}
for(int i = 1; i <= k; ++i) printf("%d\n", ans[i]);
}

CF480E Parking Lot(two-pointers + 单调队列优化)的更多相关文章

  1. BestCoder Round #89 02单调队列优化dp

    1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01  HDU 5944   水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...

  2. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  3. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  4. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  5. UESTC 880 生日礼物 --单调队列优化DP

    定义dp[i][j]表示第i天手中有j股股票时,获得的最多钱数. 转移方程有: 1.当天不买也不卖: dp[i][j]=dp[i-1][j]; 2.当天买了j-k股: dp[i][j]=max(dp[ ...

  6. poj 1821 Fence 单调队列优化dp

    /* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...

  7. 使用单调队列优化的 O(nm) 多重背包算法

    我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接. 解析 多重背包的最原始的状态转移方程: 令 c[i] = min(num[i], j / v[i]) f[i][j] = max(f[i-1][ ...

  8. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  9. uvalive4327(单调队列优化)

    这题我有闪过是用单调队列优化的想法,也想过有左右两边各烧一遍. 但是不敢确定,搜了题解,发现真的是用单调队列,然后写了好久,调了好久下标应该怎么变化才过的. dp[i][j] 表示走到第i行,第j个竖 ...

随机推荐

  1. STM32之spi管理模式

    1)sip管理模式分为:硬件管理和软件管理:主要由NSS .SSI.SSM决定: NSS是芯片上一个实实在在的引脚,SSI和SSM是SPI_CR1控制器里的的位. 值得注意的是:NSS分外部引脚和内部 ...

  2. 1.关于Python,你可能不知道的

    启示录 写在前面———— 至于python有多牛逼,这里不介绍了,安装也不说了,网上一堆一堆的安装教程. 本文只介绍需要知道的 常识知识———— 1.python 发音:英 [ˈpaɪθən] 美 [ ...

  3. docker 实践五:端口映射和容器互联

    本篇是关于 docker 容器的端口映射和容器之间的互联内容. 注:环境为 CentOS7,docker 19.03. docker 的容器除了能连接网络外,在许多时候,我们需要让多个容器来协同完成任 ...

  4. Scratch(三)剪刀石头布

    经过上一讲的突击训练,我们从门外汉开始走向编程的深坑,我们今天还要对上一讲的游戏进行加强. 上一个游戏还能演变成什么游戏呢? 我其实知道你们想到的是老hu机什么的,确实,上一个游戏改改可以变成老hu机 ...

  5. Authorization

    授权,也叫访问控制,即在应用中控制谁访问哪些资源(如访问页面/编辑数据/页面操作等).在授权中需了解的几个关键对象:主体(Subject).资源(Resource).权限(Permission).角色 ...

  6. 题解-APIO2019奇怪装置

    problem loj-3144 题意概要:设函数 \(f(t)\) 的返回值为一个二元组,即 \(f(t)=((t+\lfloor \frac tB\rfloor)\bmod A, t\bmod B ...

  7. Effective Java 读书笔记(一):创建和销毁对象

    1 构造器 => 静态工厂方法 (1)优势 静态工厂方法有名字 静态工厂方法不必在每次被调用时都产生一个新的对象 静态工厂方法能返回原返回类型的任意子类型的对象 静态工厂方法根据调用时传入的不同 ...

  8. Bootstrap4 入门

    http://www.runoob.com/bootstrap4/bootstrap4-navs.html 共五个部分 1 <!DOCTYPE html> <html lang=&q ...

  9. css 盒子 取值

    盒子:当我们设置一个标签宽高时,默认设置的是盒子里面content大小. 内容盒:content 填充盒:content+padding(overflow截取的区域) 边框盒:content+padd ...

  10. FreeRTOS 任务挂起和恢复

    在使用RTOS的时候一个实时应用可以作为一个独立的任务.每个任务都有自己的运行环境, 不依赖于系统中其他的任务或者RTOS调度器. 任何一个时间点只能有一个任务运行,具体运行哪个任务是由RTOS调度器 ...