题目大意

有一个\(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. Lombok Pojo默认初始值问题

    Lombok以注解形式来简化java代码,提高开发效率.比如我们常用的@Builder.@Data.@AllArgsConstructor.@NoArgsConstructor.@ToString等. ...

  2. 黑马vue---18、v-for指令的四种使用方式

    黑马vue---18.v-for指令的四种使用方式 一.总结 一句话总结: (item, i) in list:什么in什么的形式,前面是各种参数 1.v-for循环普通数组? <p v-for ...

  3. Android APP切换到后台接收不到推送消息

    1.   Android端进程被杀死后,目前自带的保护后台接收消息活跃机制.暂时没有什么好的机制保持任何情况下都活跃 android原生系统用home键杀进程可以起来,如果是强行停止就只能用户自己手动 ...

  4. pytorch-googleNet

    googleNet网络结构 输入网络: 由4个分支网络构成 第一分支: 由1x1的卷积构成 第二分支: 由1x1的卷积,3x3的卷积构成 第三分支: 由1x1的卷积, 5x5的卷积构成 第四分支: 由 ...

  5. 1.2 位于Shell脚本第一行的#!

    学习<shell脚本学习指南>一书,记录总结,便于自己回忆,希望对你有帮助! 2.4 自给自足的脚本:位于第一行的 #! 1.Shell脚本执行过程 当Shell执行一个程序时,会要求UN ...

  6. LC 275. H-Index II

    Given an array of citations sorted in ascending order (each citation is a non-negative integer) of a ...

  7. Android之MVVM开发模式

    MVVM 模式简介 MVVM模式是指Model-View-ViewModel.相信看过笔者关于MVP的文章的读者也会发现,无论如何抽象化,在我们的View层中是无法避免的要处理一部分逻辑的.而MVVM ...

  8. mybatis多对多映射【学生与课程】

    1)如图 2)创建students.sql和courses.sql和middles.sql drop table middles; drop table students; drop table co ...

  9. React Native安卓代码混淆和打包

    一上午就整了个React Native的打包,中间还遇到各种问题,这里还是记录下吧: 文档链接: http://reactnative.cn/docs/0.45/signed-apk-android. ...

  10. jQuery,javascript获得网页的高度和宽度【收藏】

    网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: document.body.offset ...