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. 《一头扎进》系列之Python+Selenium框架实战篇7 - 年底升职加薪,年终奖全靠它!Merry Christmas

    1. 简介 截止到上一篇文章为止,框架基本完全搭建完成.那么今天我们要做什么呢????聪明如你的小伙伴或者是童鞋一定已经猜到了,都测试完了,当然是要生成一份高端大气上档次的测试报告了.没错的,今天宏哥 ...

  2. (61)C# 可枚举类型和迭代器

    一.可枚举类型 枚举器-Enumerator  是一个只读且只能在值序列向前移动的游标 枚举器需要实现下列接口之一 System.Collections.IEnumerator System.Coll ...

  3. 点读系列《jmeter官方用户手册》

    官网:http://jmeter.apache.org/usermanual/ 说明:十八元件.十九属性.二十函数,涉及清单内容暂未仔细阅读,个人觉得一是仅供使用参考,二是适合单独写文章来解读 一.让 ...

  4. 如何在webpack开发中利用vue框架使用ES6中提供的新语法

    在webpack中开发,会遇到一大推问题,特别是babel6升级到babel7,要跟新一大推插件,而对于安装babel的功能就是在webpack开发中,vue中能够是用ES6的新特性: 例如ES6中的 ...

  5. python之正则表达式【re】

    在处理字符串时,经常会有查找符合某些规则的字符串的需求.正则表达式就是用于藐视这些规则的工具.换句话说,正则表达式是记录文本规则的代码. 1.行定位符. 行定位符就是用来表示字符串的边界,“^”表示开 ...

  6. nginx中root与alias关键字的区别

    前言 近段时间秋招上岸了,于是每天疯狂补各种分布式基础,每天都在痛苦与快乐中度过. 在学习 nginx 的时候,遇到配置上的问题:root 与 alias 的区别,卡了大概三个小时,记录下来警醒自己不 ...

  7. CF1215D

    CF1215D 两个整数的和是偶数,他们的差也是偶数 博弈好难啊qaq 我好zz啊qaq 如果M放最后一个M胜 现在和比较大的一边如果空位还多的话M胜 M可以通过在大的那边放9来消掉那边所有的空 由于 ...

  8. Redis哨兵机制(sentinel)

    1.简介: 1.是什么: Redis-Sentinel是Redis官方推荐的高可用(HA)方案,当用Reids 做master-slave高可用方案时,假如master宕机了,redis本身(包括它的 ...

  9. 子元素位于父元素中央 css实现

    wrap .box{ width: 200px; height:200px; background: pink; // 方案1 position: absolute; top:0; left:0; r ...

  10. C# Copy一个文件到另一个文件夹下

    public static void CopyToFile() { //源文件路径 string sourceName = @"D:\Source\Test.txt"; //目标路 ...