操练
2016-07-05 17:22
387 查看
问题描述 Problem Description
高老大有一个 N∗N 的广场,被均分成 N∗N 个格子。其中某些格子种上了树。为了维护世界的和平,为了贯彻和平与发展的原则,老大不得不开始操练部下了。部下们必须站在广场中某没种上树个格子中,而且一个格子内不允许有两个人站着。同时,为了显得整齐划一,部下们要维护一个方阵的阵型,也就是 N∗N 的广场内的一个 X∗Y 的矩形(该矩形的长和宽必须与广场的长和宽平行),每个格子上都必须有一个部下。现在老大想知道,一次最多操练多少个部下?
输入描述 Input Description
输入第一行两个正整数 N 和 M ,代表广场的长和宽。接一个 N 行 M 列的字符矩阵,若第 I 行第 J 列为 0 则代表该格子上有一颗树。
输出描述 Output Description
输出一次最多能够操练的部下个数。输入样例 Sample Input
211
11
输出样例 Sample Output
4数据范围及提示 Data Size & Hint
对于 80% 的数据, N≤250;对于 100% 的数据, N≤1000 。
分析 I Think
记 si,j 表示在 (i,j) 的上面(含)有连续多少个 1 ,若 ai,j=0,则 si,j=0 ,然后枚举每一行的 si ,再用一个单调队列来维护,要求队列中的每一个元素都比前面的元素大,他们的入队时间,记列的编号,每当有元素弹出时就更新 ans。代码 Code
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Size = 1010; int a[Size][Size]; int up[Size][Size]; int stack[Size],top; int time[Size]; int n; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ scanf("%1d",&a[i][j]); if(a[i][j]) up[i][j] = up[i-1][j]+1; } for(int i=1;i<=n;++i) up[i][n+1] = -1; int ans = 0; for(int i=1;i<=n;++i){ stack[top=0] = -1; for(int j=1;j<=n+1;++j) if(up[i][j] > stack[top]){ stack[++top] = up[i][j]; time[top] = j; } else{ while(top && up[i][j]<stack[top]){ ans = max(ans,stack[top]*(j-time[top])); --top; } if(stack[top] != up[i][j]) stack[++top] = up[i][j]; } } printf("%d",ans); return 0; }
相关文章推荐
- java spring mvc restful 上传文件
- Leetcode练习笔记——169. Majority Element
- js自定义事件及事件交互原理概述(二)
- Oracle处理CLOB超过4000入库问题 (2)
- nginx.conf配置
- .net core相关博客
- python之当前标准时间显示
- IntelliJ IDEA centos安装
- 地址接口获取数据失败时,应该注意的,应判断查询时否成功
- tyvj P1864 [Poetize I]守卫者的挑战
- cmake:在Makefile中运行ant脚本
- 我不想写背景
- MySQL之【钻石】抢购风暴
- 文件为只读模式,且无法更改权限
- SVN 命令行操作
- Java常用类库——数字格式化(NumberFormat)与大数操作(BigIntger、BigDecimal类)
- Angularjs-2 (basic)
- JMS学习(五)--ActiveMQ中的消息的持久化和非持久化 以及 持久订阅者 和 非持久订阅者之间的区别与联系
- Mantis修改“严重性”字段内容
- .net core相关博客