51nod1787最大子方阵

我在51nod上面切的第一道题

我在51nod上面切的第一道8级题

我在51nod上面切的第一道8级题的一血

题目大意

有一个n*m的矩阵,矩阵中的每一个元素是'X'或者'.',现在有若干次修改操作,每次修改操作是将某一个'.'改成'X',修改之后要求计算出当前矩阵里面只包含'.'的最大子方阵是多大,输出方阵的边长即可。

输入

单组测试数据。

第一行有三个整数n, m 和 k(1<=n,m,k<=2000),分别表示矩阵的大小和修改次数。

接下来n行,每一行有m个字符'X'或者'.'。

接下来k行,每一行有两个整数 xi, yi (1≤xi≤n, 1≤yi≤m),表示所修改点的标。

输入保证所给的坐标上面的字符一定是'.'。

输出

输出k行,对应每次修改之后的最大子方阵的边长。

题解

首先倒过来做,把加‘X’改成删‘X’。

最初的答案可以二分答案求

假如删掉(x,y)处的‘X’答案变大了,那么答案矩阵显然包括(x,y)

于是考虑求包含(x,y)的最大合法子矩阵。

维护mal[x][y],mar[x][y]表示(x,y)向左向右能扩展到的最长距离。

那么假设新答案矩阵的上边界为l,下边界为r,保证左右宽度始终大于等于上下长度(即r-l+1)

l向下移的时候r肯定单调向下移。

所以复杂度是O(\(n^2\))的

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,m,k,i,l,r,mid,x,y;
char map[2005][2005];
int sum[2005][2005];
int mal[2005][2005],mar[2005][2005];
int exl[2005],exr[2005];
int q[2005][2];
int ans[2005]; void preprocess()
{
int i,j;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
if (map[i][j]=='X')
sum[i][j]++;
}
}
} int pd(int len)
{
int i,j;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
if ((i+len-1>n)||(j+len-1>m)) continue;
if (sum[i+len-1][j+len-1]-sum[i-1][j+len-1]-sum[i+len-1][j-1]+sum[i-1][j-1]==0) return 1;
}
}
return 0;
} int getans()
{
preprocess();
if (sum[n][m]==n*m) return 0;
l=1;
r=min(n,m);
mid=(l+r+1)/2;
while (l<r)
{
if (pd(mid)==1)
l=mid;
else
r=mid-1;
mid=(l+r+1)/2;
}
return mid;
} int update(int x)
{
int y;
for (y=1;y<=m;y++)
{
if (map[x][y]=='X') mal[x][y]=0;
else mal[x][y]=mal[x][y-1]+1;
}
for (y=m;y>=1;y--)
{
if (map[x][y]=='X') mar[x][y]=0;
else mar[x][y]=mar[x][y+1]+1;
}
} int main()
{
freopen("read.in","r",stdin);
scanf("%d%d%d",&n,&m,&k);
for (i=1;i<=n;i++)
{
scanf("%s",map[i]+1);
}
for (i=1;i<=k;i++)
{
scanf("%d%d",&q[i][1],&q[i][2]);
map[q[i][1]][q[i][2]]='X';
}
ans[k]=getans();
for (i=1;i<=n;i++)
{
update(i);
}
for (i=k;i>=1;i--)
{
x=q[i][1];
y=q[i][2];
map[x][y]='.';
update(x);
exl[x]=mal[x][y];
exr[x]=mar[x][y];
for (l=x-1;l>=1;l--)
{
exl[l]=min(exl[l+1],mal[l][y]);
exr[l]=min(exr[l+1],mar[l][y]);
}
for (r=x+1;r<=n;r++)
{
exl[r]=min(exl[r-1],mal[r][y]);
exr[r]=min(exr[r-1],mar[r][y]);
}
r=x;
for (l=1;l<=x;l++)
{
while ((r+1<=n)&&(min(exl[l],exl[r+1])+min(exr[l],exr[r+1])-1>=r-l+1))
{
r++;
}
if (min(exl[l],exl[r])+min(exr[l],exr[r])-1>=r-l+1)
ans[i-1]=max(ans[i-1],r-l+1);
}
ans[i-1]=max(ans[i-1],ans[i]);
}
for (i=1;i<=k;i++)
{
printf("%d\n",ans[i]);
}
}

51nod1787最大子方阵的更多相关文章

  1. [CTCI] 最大子方阵

    最大子方阵 题目描述 有一个方阵,其中每个单元(像素)非黑即白(非0即1),请设计一个高效算法,找到四条边颜色相同的最大子方阵. 给定一个01方阵mat,同时给定方阵的边长n,请返回最大子方阵的边长. ...

  2. 2013 Multi-University Training Contest 2

    HDU-4611 Balls Rearrangement 题意:具体题意不大清楚,最后要处理一个这样的表达式:sum{ |i % a - i % b| },0 <= i < N 的取值很大 ...

  3. bzoj 1057 单调栈

    首先我们可以枚举每个一点,然后向下一直拓展到不能拓展为止,然后向下拓展的同时我们可以算出来向左最多拓展的个数,用单调栈来维护一个上升的序列,这样就类似与悬线法找最大01子矩阵了,但是对于这题01交替来 ...

  4. [LeetCode] Maximum Size Subarray Sum Equals k 最大子数组之和为k

    Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If t ...

  5. [LeetCode] Maximum Product Subarray 求最大子数组乘积

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  6. [LeetCode] Maximum Subarray 最大子数组

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  7. 求一个数组的最大子数组(C/C++实现)

    最大子数组:要求相连,加起来的和最大的子数组就是一个数组的最大子数组.编译环境:VS2012,顺便说句其实我是C#程序员,我只是喜欢学C++. 其实这是个半成品,还有些BUG在里面,不过总体的思路是这 ...

  8. 在Eclipse中使用Junit进行单元测试练习 实现最大子数组和算法

    1.如何在MAC OS X下安装配置java开发工具 http://www.cnblogs.com/coderL/p/5939541.html 2.最大子数组和算法 附上程序运行及测试截图,源码见后 ...

  9. 洛谷P1101 单词方阵——S.B.S.

    题目描述 给一nXn的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间[color=red ...

随机推荐

  1. 正则匹配class并替换整个class为空

    str.replace(/class=[\"|'](.*?)[\"|'].*?/g, '')

  2. HTML5: HTML5 Video(视频)

    ylbtech-HTML5: HTML5 Video(视频) 1.返回顶部 1. HTML5 Video(视频) 很多站点都会使用到视频. HTML5 提供了展示视频的标准. 检测您的浏览器是否支持 ...

  3. OO七大设计原则

    一.单一职责原则(Single Responsibility Principle,SRP) 含义: 1.避免相同的职责分散到不同的类中 2.避免一个类承担太多职责 作用: 1.可以减少类之间的耦合 2 ...

  4. python base64编码实现

    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" def encode(b ...

  5. LVM-扩容目录

    LVM LVM是一种源自Unix环境,在Linux上广泛应用的逻辑虚拟盘存储方案.借助LVM,可以在保证各个Linux目录分区稳定,又可以实现各目录存储资源灵活分配. 本文主要系统介绍Linux环境下 ...

  6. uoj#186 【UR #13】Yist

    题目 orz myy 首先注意到答案有单调性,于是我们可以考虑二分一个\(x\),之后去判断一下每次只使用长度为\(x\)的区间能否删出目标序列 显然我们应该贪心地删除需要删除元素中最小的那一个,感性 ...

  7. rpcbind服务没法开启问题

    昨天下午有部分生产机器无法启动nfs服务:报错很是奇怪.于是一路顺藤摸瓜发现是rpcbind没能正常启动导致的nfs没能起来. 后来总结了两种办法:主要是ipv6的问题所导致的. 措施一: 报错内容 ...

  8. nuxt项目在windows环境下安装部署

    1.nodejs安装,地址 https://nodejs.org/en/ 2.在本地项目中运行npm  run build  命令将开发好的项目打包生成.nuxt文件夹,然后把.nuxt文件夹.nux ...

  9. 理解Java GC日志

    idea 在vm options处加入-XX:+PrintGCDetails,可打印GC日志. public class ReferenceCountingGC { public Object ins ...

  10. syslog-ng收集日志+ELK平台搭建教程

    syslog-ng部署: 用于接收交换机输出的日志. syslog-ng安装很简单,可以顺便搜一下,文章有很多.我是yum直接安装的. syslog-ng配置: vi /etc/syslog-ng/s ...