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. 有关JWT(Json Web Token)的那些事

    用户认证是计算机安全领域一个永恒的热点话题,然而你会发现,开发者很少讨论有关Json Web Token的话题,其实使用Json Web Token集成到API身份验证机制中是容易,本文给大家普及基础 ...

  2. Openstack组件部署 — Keystone功能介绍与认证实现流程

    目录 目录 前文列表 Keystone认证服务 Keystone认证服务中的概念 Keystone的验证过程 简单来说 前文列表 Openstack组件部署 - Overview和前期环境准备 Ope ...

  3. Reactor 反应堆设计模式

    为了应对高并发的服务器端开发,微软在2009年提出了一种更优雅地实现异步编程的方式Reactive Programming即反应式编程.随后其他技术紧随其后,比如ES6通过引入类似的异步编程方式等. ...

  4. Java语言基础及java核心

    一.Java语言特点 1. 简单 2. 面向对象 3. 分布式 4. 健壮 5. 安全 6. 中性架构跨平台 7. 超强的可移植性 8. 高性能 9. 多线程 二.java的环境变量 JAVA_HOM ...

  5. UVA1632_Alibaba

    题目链接 大致题意:直线上面有n个点,第i个点坐标为xi,它会在di时间消失,你可以选择从任何位置出发,求访问完所有点的最短时间,无解输出no solution 思路:这有一个难点就是,不知道状态该怎 ...

  6. Python之os.path.join()

    os.path.join()函数用于路径拼接文件路径. os.path.join()函数中可以传入多个路径: 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃. 以上一种情况为先.在上一种情况 ...

  7. css3 新特性(动画)

    1. 制作动画 先定义动画,再使用(调用)动画 使用 keyframes(关键帧)定义动画(类似定义类选择器) @keyframes 动画名称{ 0%{ width:100px; } 100%{ wi ...

  8. Spark使用Java读取mysql数据和保存数据到mysql

    原文引自:http://blog.csdn.net/fengzhimohan/article/details/78471952 项目应用需要利用Spark读取mysql数据进行数据分析,然后将分析结果 ...

  9. npm install 时 提示err code EINTEGRITY报错

    1.报错截图如图: 2.报错缘由:因npm 版本问题导致 3.解决方法:升级npm版本(npm i -g npm),再重新npm install即可.

  10. Java中date和calendar的用法

    获取现在系统的时间和日期看起来是一件非常神奇的事情,但是当使用date和calendar之后发现仍然非常神奇. 1.date 使用date日期之前需要导入包: import java.text.Sim ...