51nod1787最大子方阵
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最大子方阵的更多相关文章
- [CTCI] 最大子方阵
最大子方阵 题目描述 有一个方阵,其中每个单元(像素)非黑即白(非0即1),请设计一个高效算法,找到四条边颜色相同的最大子方阵. 给定一个01方阵mat,同时给定方阵的边长n,请返回最大子方阵的边长. ...
- 2013 Multi-University Training Contest 2
HDU-4611 Balls Rearrangement 题意:具体题意不大清楚,最后要处理一个这样的表达式:sum{ |i % a - i % b| },0 <= i < N 的取值很大 ...
- bzoj 1057 单调栈
首先我们可以枚举每个一点,然后向下一直拓展到不能拓展为止,然后向下拓展的同时我们可以算出来向左最多拓展的个数,用单调栈来维护一个上升的序列,这样就类似与悬线法找最大01子矩阵了,但是对于这题01交替来 ...
- [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 ...
- [LeetCode] Maximum Product Subarray 求最大子数组乘积
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- [LeetCode] Maximum Subarray 最大子数组
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- 求一个数组的最大子数组(C/C++实现)
最大子数组:要求相连,加起来的和最大的子数组就是一个数组的最大子数组.编译环境:VS2012,顺便说句其实我是C#程序员,我只是喜欢学C++. 其实这是个半成品,还有些BUG在里面,不过总体的思路是这 ...
- 在Eclipse中使用Junit进行单元测试练习 实现最大子数组和算法
1.如何在MAC OS X下安装配置java开发工具 http://www.cnblogs.com/coderL/p/5939541.html 2.最大子数组和算法 附上程序运行及测试截图,源码见后 ...
- 洛谷P1101 单词方阵——S.B.S.
题目描述 给一nXn的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间[color=red ...
随机推荐
- uuid 去中心化的唯一性
A Universally Unique IDentifier (UUID) URN Namespace https://tools.ietf.org/html/rfc4122.html A UUID ...
- 数据访问层的接口IBaseDAL
using System; using System.Collections; using System.Data; using System.Data.Common; using System.Co ...
- AutoFac控制反转 转载https://blog.csdn.net/u011301348/article/details/82256791
一.AutoFac介绍 Autofac是.NET里IOC(Inversion of Control,控制反转)容器的一种,同类的框架还有Spring.NET,Unity,Castle等.可以通过NuG ...
- JWT工具类
package com.ynhrm.common.utils; import io.jsonwebtoken.Claims;import io.jsonwebtoken.JwtBuilder;impo ...
- 引用so动态链接库的方法
from ctypes import cdll lib = cdll.LoadLibrary('/home/zhengli/test/test.so') lib.func() 总结: 1.引用ctyp ...
- 利用单选框的单选特性作tab切换
<RadioGroup v-model="selectType" type="button" @onchange="selectTypeChan ...
- Invoke-Obfuscation混淆ps文件绕过Windows_Defender
前提 powershell只能针对win7之后的系统,之前的win操作系统默认没有安装powershell. 所在目录:C:\Windows\System32\WindowsPowerShell\v1 ...
- Install ncurses (ncurses-devel) and try again
apt install libncurses5-dev libncursesw5-dev
- vue在element-ui的dialog弹出框中加入百度地图
参考:https://blog.csdn.net/u012724595/article/details/82703579 <!-- gps弹窗 --> <el-dialog v-di ...
- transform:translate(-50%,-50%)
和父亲元素没关系,走自己盒子宽度一半