极其考思维的好题

题目背景

众所周知,$\mathrm{Zdrcl}$是一名天天$\mathrm{AK}$的高水平选手。

作为一民长者,为了向大家讲述自己$\mathrm{AK}$的经验,他决定在一个礼堂里为大家举办一场演讲。

题目描述

这个礼堂拥有$N\times M$个位子,排成$N$行$M$列。每个位子都有一盏灯,一开始有的灯是亮的,有的灯是灭的。这个礼堂十分诡异,人们操作一次只能使某一行或某一列(某一行或某一列由操作者你自己来决定)的灯的明暗状态全都发生转变(显然,我们不一定可以把所有的灯都点亮)。

来听演讲的人只会坐在灯已经被点亮的位置, 所以可以听演讲的位置只会是一个只由灯是亮的的位子所组成的矩形(不然坐太乱,$\mathrm{Zdrcl}$会不高兴的) 。

$\mathrm{Zdrcl}$知道会有很多人来听演讲, 所以他希望找到一个经过若干操作后的面积最大的只由灯是亮的的位子所组成的矩形。 这个任务当然由想$\mathrm{AK}$的你来完成啦!

输入输出格式

输入格式:

第一行两个正整数表示$N,M$。

接下来有$N$行,每行有$M$个字符(‘#’表示这个灯初始状态是亮的,‘.’表示这个灯初始状态是暗的)。

输出格式:

一行一个整数表示你找到的矩形的面积。

输入输出样例

输入样例#1:

3 3
..#
##.
.#.

输出样例#1:

6

输入样例#2:

4 6
.#....
...###
.##.#.
...#..

输出样例#2:

9

说明

样例1解释

数据范围

对于$5\%$的数据:$N=2,M=2$

对于$15\%$的数据:$N\times M\le 8$

对于$30\%$的数据:$N,M\le 10$

对于$60\%$的数据:$N\le 1\le 10^2$

对于$80\%$的数据:$N\le 4\times 10^2$

对于$100\%$的数据:$N\le 2\times 10^3$

输入文件比较大, 请使用比较快速的读入方法。

提示

这一题写起来不是很困难。

题解:

    这个题只要第一步想对了,剩下的DP部分就不难写。主要就是考虑怎么判断是否能全部点亮。

    多次手玩可以发现对于可以被全部点亮的部分的特性。因为异或的逆运算还是异或,灯的开关就是在异或。因此我们考虑把矩阵转化为0和1。

    上面提到灯的开关是进行了异或,因此对于任意行或列的操作,它们的顺序是可以被打乱的。我们假设先进行列操作,我们要尽可能把序列变为形如

00000
11111
11111
00000

这样,才能在之后只进行行操作时可以完成矩阵的变换。

    那么上面给出的矩阵原来可能是这样的

01001
10110
10110
01001

    可以发现,它们左右异或的结果总是一列均为1或一列均为0。因为如果一列均为1的话,那么只需要对其中一列进行反转即可;如果一列均为0的话,这两列就是一样的,可以对它们进行相同的操作而达到目的。

1101
1101
1101
1101

    不过这样异或会使得矩阵的宽度减小1,我们只需要在计算的时候把这一维加上1就可以了,因为有$latex x$个异或结果,代表了$latex x+1$列。最后再单独处理最优解只占一列的特殊情况。

    而有了这样的矩阵,我们的目的就是求最大子矩阵,其中每一列的数字都相同。这样用单调栈可以做到$latex O(nm)$。

当时出题人给出的解法是通过前5%的数据找规律,发现对于一个合法的矩阵,它内部的每一块2×2区域都满足“两种状态出现的次数都是偶数”。
即0出现0次,1出现4次/0出现4次,1出现0次/0出现2次,1出现2次。这样的话感觉条件变少了,不过正确性也可以保证,暂时不写代码。(咕

Code:

#include<cstdio>
#include<cstring>
char c[2222][2222];
int Xor[2222][2222];
int con[2222];
int q[2222],l=0,r=0;
int ext[2222];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%s",c[i]+1); int ans=1,tt=1;
for(int i=1;i<=n;++i)
{
tt=1;
for(int j=1;j<=m;++j)
if(c[i][j]==c[i][j-1])
{
++tt;
ans=ans>tt?ans:tt;
}
else
tt=1;
}
for(int i=1;i<=m;++i)
{
tt=1;
for(int j=1;j<=n;++j)
if(c[i][j]==c[i-1][j])
{
++tt;
ans=ans>tt?ans:tt;
}
else
tt=1;
}
for(int i=1;i<n;++i)
for(int j=1;j<=m;++j)
Xor[i][j]=(c[i][j]!=c[i+1][j]);
for(int i=1;i<=m;++i)
{
l=0,r=0;
for(int j=1;j<n;++j)
{
if(i==1||Xor[j][i]!=Xor[j][i-1])
con[j]=1;
else
con[j]++;
int cnt=0;
while(l<r&&con[j]<con[q[r]])
{
int tmp=(j-q[r]+1+ext[r])*(con[q[r]]);
ans=ans>tmp?ans:tmp;
cnt+=ext[r]+1;//好久没用单调栈做题了,忘记还要加上之前延伸的块……
--r;
}
q[++r]=j;
ext[r]=cnt;
}
for(int j=l+1;j<=r;++j)
{
int tmp=(n-q[j]+1+ext[j])*(con[q[j]]);
ans=ans>tmp?ans:tmp;
}
}
printf("%d\n",ans);
return 0;
}

  

【DP】【构造】NOIp模拟题 演讲 题解的更多相关文章

  1. 一些noip模拟题一句话题解

    Problem A: 序列 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 12  Solved: 9[Submit][Status][Web Boar ...

  2. 【入门OJ】2003: [Noip模拟题]寻找羔羊

    这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...

  3. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

  4. 8.22 NOIP 模拟题

      8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...

  5. 9.9 NOIP模拟题

    9.9 NOIP模拟题 T1 两个圆的面积求并 /* 计算圆的面积并 多个圆要用辛普森积分解决 这里只有两个,模拟计算就好 两圆相交时,面积并等于中间两个扇形面积减去两个三角形面积 余弦定理求角度,算 ...

  6. noip模拟题题解集

    最近做模拟题看到一些好的题及题解. 升格思想: 核电站问题 一个核电站有N个放核物质的坑,坑排列在一条直线上.如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 任务:对于给定 ...

  7. NOIP模拟题17.9.26

    B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...

  8. PAT甲级 模拟题_C++题解

    模拟题 PAT (Advanced Level) Practice 模拟题 目录 1008 Elevator (20) 1042 Shuffling Machine (20) 1046 Shortes ...

  9. 【noip模拟题】迎接仪式(dp+特殊的技巧)

    好神的一题... 这是一道DP题,本题的难点在于状态的确定,由于调整是任意的,很难划分状态,我们略微修改一下调整的形式:把一次’j’和’z’交换看做两次变换:’j’->’z’;’z’->’ ...

随机推荐

  1. C++ 重载操作符- 01 简单的入门

    重载操作符的定义 这篇博客是对 重载操作符 的一个概要性的介绍. 重载操作符是C++语言的高级功能,当我们写一个类的时候,可以根据需要学一个重载操作符,如果 不需要,我们可以不写. 大量的操作符都可以 ...

  2. algorithm notes

    1.算法可视化 https://visualgo.net/en

  3. Linux gtypist

    一.简介 Typist (gtypist)是一个打字练习软件,用来提升打字的速度.   二.安装 1)源码方式 http://ftp.gnu.org/gnu/gtypist/   三.使用 http: ...

  4. Why does my Authorize Attribute not work?

    the roles of a ClaimsPrincipal are actually just claims create with a type of ClaimsIdentity.RoleCla ...

  5. [GO]冒泡排序的原理和代码实现

    冒泡排序的原理:对于一个数组里所有的元素进行两两比较,发生大于则变换数组下标则为升序排序,发生小于则变换数据下标的则为降序排序 比如给定的数组为[1, -2, 3, -4],对于我们的需求,两两比较后 ...

  6. Java IO输入输出流 字符数组流 ByteArrayOutputStream/ByteArrayInputStream

    private static void StringWriterAndReader() throws Exception { //字符串流(字符串的内存流) //字符串输入流 StringWriter ...

  7. (转)jquery仿天猫商城左侧导航菜单

    原文地址:http://www.cnblogs.com/WinKi/p/3398824.html 之前看到有博友写了一个仿天猫商城左侧导航菜单,可惜不提供免费下载,也没有代码.以前自己也写过类似的效果 ...

  8. 【Java】对Map按key和value分别排序

    一.什么是Map? 在讲解Map排序之前,我们先来稍微了解下map. map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. ...

  9. HackFifteen 移除背景以提升Activity启动速度

    1.概要:     移除窗口默认背景是提升应用程序启动速度的一个简单技巧.判断是否需要移除背景的原则很简单:如果应用程序界面需要 占据窗口100%的控件,就需要将windowBackground属性设 ...

  10. ubuntu没有权限(不能)创建文件夹(目录)

    可以在终端直接运行 sudo nautilus,弹出来的nautilus可以直接GUI操作,中途别关终端.如果遇到需要输入root密码,则输入root密码就可以启动这个图形界面了.