题目大意

有一个\(n\times m\)的网格,每个位置是黑色或者白色。\(k\)个操作,每个操作是将一个白格子染黑,操作后输出当前最大的白色正方形的边长。\(n,m,k\leq 2\times 10^3\)

题解

发现在每次操作是把白格子变黑,会使答案变小。维护“变小的最大值”听上去不太舒服。考虑把操作全都反过来,变成把黑格子染白。

这样每次操作之后,如果答案变大了,那么新的答案正方形一定包含在被操作的格子。

考虑对每个点记它左边最左的白格子和右边最右的白格子,操作时暴力更新与被操作点同行的点。

答案就是想找连续的一段与被操作的点在同一列,“段的长度”与“最左的右边界-最右的左边界”的最小值尽可能大。

发现可以判断答案是否大于一个数\(x\):当这一列上存在一个点,满足该点到从该点往上数第\(x\)个点满足“最左的右边界-最右的左边界”不少于\(x\),\(x\)就可以;反之就不可以。

可以用线段树或单调队列维护区间最左右边界和最右左边界。

这题知道判断解是否合法的方法后也不用二分,因为在处理过后答案就是不降的,而且不会超过\(min(n,m)\),而判断能否使答案增加1需要\(\Theta(n)\)或\(\Theta(n\space log\space n)\)的时间复杂度,所以可以每次暴力判断能否使答案增加。

总时间复杂度\(\Theta(n\times m+k\times m+k\times n)\)。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 2007
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
char ch[20];int f=0;
if(!x){putchar('0'),putchar('\n');return;}
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
int qx[maxn],qy[maxn],q[maxn],hd,tl;
int col[maxn][maxn],ans,lmx[maxn][maxn],rmx[maxn][maxn],n,m,k,res[maxn],tmp[maxn],dp[maxn][maxn];
char s[maxn];
int jud(int yy)
{
hd=1,tl=0;
rep(i,1,n)
{
while(hd<=tl&&q[hd]<i-(ans+1)+1)hd++;
while(hd<=tl&&lmx[q[tl]][yy]<=lmx[i][yy])tl--;
q[++tl]=i;
if(i<ans+1)continue;
tmp[i]=yy-lmx[q[hd]][yy]+1;
}
hd=1,tl=0;
rep(i,1,n)
{
while(hd<=tl&&q[hd]<i-(ans+1)+1)hd++;
while(hd<=tl&&rmx[q[tl]][yy]>=rmx[i][yy])tl--;
q[++tl]=i;
if(i<ans+1)continue;
tmp[i]+=rmx[q[hd]][yy]-yy;
}
rep(i,ans+1,n)if(tmp[i]>=ans+1)return 1;
return 0;
}
int main()
{
n=read(),m=read(),k=read();
rep(i,1,n)
{
scanf("%s",s+1);
rep(j,1,m)if(s[j]!='.')col[i][j]=1;
}
rep(i,1,k)qx[i]=read(),qy[i]=read(),col[qx[i]][qy[i]]=1;
rep(i,1,n)
{
rep(j,1,m)
{
if(col[i][j]){lmx[i][j]=j+1;continue;}
dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
ans=max(dp[i][j],ans);
if(j==1||col[i][j-1])lmx[i][j]=j;
else lmx[i][j]=lmx[i][j-1];
}
dwn(j,m,1)
{
if(col[i][j]){rmx[i][j]=j-1;continue;}
if(j==m||col[i][j+1])rmx[i][j]=j;
else rmx[i][j]=rmx[i][j+1];
}
}
dwn(i,k,1)
{
res[i]=ans;
col[qx[i]][qy[i]]=0;
int nl=qy[i],nr=qy[i];
while(nl-1>=1&&!col[qx[i]][nl-1])nl--;
while(nr+1<=m&&!col[qx[i]][nr+1])nr++;
rep(j,nl,nr)lmx[qx[i]][j]=nl,rmx[qx[i]][j]=nr; while(jud(qy[i]))ans++;
}
rep(i,1,k)write(res[i]);
return (0-0);
}

并不对劲的CF480E:Parking Lot的更多相关文章

  1. [CF480E]Parking Lot

    题意:给一个$n\times m$的网格,初始时有些地方不能选,给$k$个询问$(x,y)$,每次令$(x,y)$不能选,然后询问最大子正方形的边长 如果按原题来做,禁止选一个点对答案的影响是极其鬼畜 ...

  2. CF480E Parking Lot(单调队列+dp然鹅并不是优化)

    (全英文题面所以直接放化简题意) 题意:在一个二维平面内,初始有一些点,然后每个时间点加入一些点,对每个时间点求平面内最大的无障碍正方形 (这次的题目是真的神仙啊...) 首先,考虑暴力,如果对每一个 ...

  3. CF480E Parking Lot(two-pointers + 单调队列优化)

    题面 动态加障碍物,同时查询最大子正方形. n,m≤2000n,m\leq2000n,m≤2000 题解 加障碍不好做,直接离线后反着做,每次就是清除一个障碍物. 显然倒着做答案是递增的,而且答案的值 ...

  4. [LintCode] Parking Lot 停车场问题

    Design a parking lot. see CC150 OO Design for details.1) n levels, each level has m rows of spots an ...

  5. [CareerCup] 8.4 Parking Lot 停车场问题

    8.4 Design a parking lot using object-oriented principles. LintCode上的原题,请参见我的另一篇博客Parking Lot 停车场问题. ...

  6. Codeforces 46D Parking Lot

    传送门 D. Parking Lot time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  7. Codeforces Round #135 (Div. 2) E. Parking Lot 线段数区间合并

    E. Parking Lot time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. Amazon Interview Question: Design an OO parking lot

    Design an OO parking lot. What classes and functions will it have. It should say, full, empty and al ...

  9. HDOJ(HDU) 1673 Optimal Parking

    Problem Description When shopping on Long Street, Michael usually parks his car at some random locat ...

随机推荐

  1. LVS之ipvsadm命令

    目录: 安装 基本描述 用法 命令选项 示例 [安装] 可使用yum安装或者从官网下载安装包源码安装,两种方式皆可 先检查是否已经安装ipvsadm [root@v_machine1 ~]# yum ...

  2. IntelliJ IDEA 2017.3 搭建一个多模块的springboot项目(三)

    你得先看完前两篇文章才可以进行第三章.这章我又新建了一个模块,起名叫project-core.建立方式与(一)里面一致,一个普通的maven模块.不需要勾选archetype的那种. 大家自己建好后, ...

  3. ionic3引用外部插件--百度地图及echart报表的使用

    前言 ionic3提供的组件已经相当丰富咯,但是事实上有些特殊的需求,比如使用百度地图,或者第三方插件echart报表插件是,就不能用传统的方式去使用第三方插件咯,如何在Ionic3项目中使用第三方J ...

  4. Java获取当前时间及String、datetime、date相互转化

    一.获取当前系统时间和日期并格式化输出: import java.util.Date; import java.text.SimpleDateFormat; public class NowStrin ...

  5. HearthBuddy CSharpCodeProvider 如何编译cs文件

    源码 源码1 namespace Hearthbuddy.Windows{    // Token: 0x02000041 RID: 65    public class MainWindow : W ...

  6. qt 之http学习

    在Qt网络编程中,需要用到协议,即HTTP.它是超文本传输协议,它是一种文件传输协议. 新建工程名为“http”,然后选中QtNetwork模块,最后Base class选择QWidget.注意:如果 ...

  7. 前端知识点回顾之重点篇——jQuery实现的原理

    jQuery jQuery的实现原理 参考:https://blog.csdn.net/zhouziyu2011/article/details/70256659 外层沙箱和命名空间$ 为了避免声明了 ...

  8. 1.ibatis核心类

  9. Ubuntu16.04格式化U盘

    root@ubuntu:~# fdisk -l root@ubuntu:~# fdisk /dev/sdb 格式化U盘: root@ubuntu:~# fdisk -l sudo mkfs.ntfs ...

  10. mysql锁表机制分析

    http://blog.csdn.net/u010942020/article/details/51925653