2019牛客暑期多校训练营(第二场) - H - Second Large Rectangle - dp
https://ac.nowcoder.com/acm/contest/882/H
正确的办法:dp1[i][j]表示以i,j为底的矩形的高。得到dp1之后,dp2[i][j]表示以dp1[i][j]悬线向左能移动的极限(用单调栈)。
维护最后答案的时候单调栈是>=的,这样同高的就不会重复计算。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ERR(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {cerr << "\n";}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << *it << "=" << a << ", ";
err(++it, args...);
}
#define ERR1(arg,n) { cerr<<""<<#arg<<"=\n "; for(int i=1;i<=n;i++) cerr<<arg[i]<<" "; cerr<<"\n"; }
#define ERR2(arg,n,m) { cerr<<""<<#arg<<"=\n"; for(int i=1;i<=n;i++) { cerr<<" "; for(int j=1;j<=m;j++)cerr<<arg[i][j]<<" "; cerr<<"\n"; } }
#define REP(i, a, b) for(int i = a; i <= b; ++i)
int n, m;
char g[1005][1005];
int dp1[1005][1005], dp2[1005][1005];
int stk1[1005], top;
int max1, max2;
void update(int val) {
if(val > max2)
max2 = val;
if(max2 > max1) {
int t = max2;
max2 = max1;
max1 = t;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
//freopen("Yinku.err", "w", stderr);
#endif // Yinku
scanf("%d%d", &n, &m);
REP(i, 1, n) scanf("%s", g[i] + 1);
REP(j, 1, m) dp1[1][j] = (g[1][j] - '0');
REP(i, 2, n) REP(j, 1, m) dp1[i][j] = (g[i][j] - '0') ? (dp1[i - 1][j] + 1) : 0;
REP(i, 1, n) {
dp2[i][1] = 1;
top=0;
stk1[++top]=1;
REP(j, 2, m) {
int tmp=j;
while(top&&dp1[i][stk1[top]]>=dp1[i][j]){
tmp=stk1[top];
--top;
}
dp2[i][j]=tmp<j?dp2[i][tmp]:j;
stk1[++top]=j;
}
}
//ERR2(dp1, n, m);
//ERR2(dp2, n, m);
max1 = 0, max2 = 0;
REP(i, 1, n) {
top = 0;
REP(j, 1, m) {
while(top && dp1[i][stk1[top]] >= dp1[i][j]) {
int h = dp1[i][stk1[top]];
int w = j-1-dp2[i][stk1[top]]+1;
//ERR(stk1[top],w*h);
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
stk1[++top] = j;
}
while(top) {
int h = dp1[i][stk1[top]];
int w = m-dp2[i][stk1[top]]+1;
//ERR(stk1[top],w*h);
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
//cerr<<endl;
}
printf("%d\n", max2);
}
小心这个样例
5 6
110000
011000
101100
110100
111010
5 6
110010
011111
101110
110111
111010
错误代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ERR(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {cerr << "\n";}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << *it << "=" << a << ", ";
err(++it, args...);
}
#define ERR1(arg,n) { cerr<<""<<#arg<<"=\n "; for(int i=1;i<=n;i++) cerr<<arg[i]<<" "; cerr<<"\n"; }
#define ERR2(arg,n,m) { cerr<<""<<#arg<<"=\n"; for(int i=1;i<=n;i++) { cerr<<" "; for(int j=1;j<=m;j++)cerr<<arg[i][j]<<" "; cerr<<"\n"; } }
#define REP(i, a, b) for(int i = a; i <= b; ++i)
int n, m;
char g[1005][1005];
int dp[1005][1005];
int stk[1005], top;
int max1, max2;
void update(int val) {
if(val > max2)
max2 = val;
if(max2 > max1) {
int t = max2;
max2 = max1;
max1 = t;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d%d",&n,&m);
REP(i, 1, n) scanf("%s", g[i] + 1);
REP(j, 1, m) dp[1][j] = (g[1][j] - '0');
REP(i, 2, n) REP(j, 1, m) dp[i][j] = (g[i][j] - '0') ? (dp[i - 1][j] + 1) : 0;
ERR2(dp, n, m);
max1 = 0, max2 = 0;
REP(i, 1, n) {
top = 0;
REP(j, 1, m) {
while(top && dp[i][stk[top]] > dp[i][j]) {
int h = dp[i][stk[top]];
int w = (j - 1) - stk[top]+1;
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
stk[++top] = j;
}
while(top) {
int h = dp[i][stk[top]];
int w = m - stk[top];
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
}
printf("%d\n", max2);
}
错误在于虽然把3弹出来了但其实2是可以延伸过去的。也就是单调栈一直弹出东西的时候都是可以延伸过去的,那干脆演一波算了。
虽然通过了错误代码1,但是没有计算悬线向左最远距离的方法是错的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ERR(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {cerr << "\n";}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << *it << "=" << a << ", ";
err(++it, args...);
}
#define ERR1(arg,n) { cerr<<""<<#arg<<"=\n "; for(int i=1;i<=n;i++) cerr<<arg[i]<<" "; cerr<<"\n"; }
#define ERR2(arg,n,m) { cerr<<""<<#arg<<"=\n"; for(int i=1;i<=n;i++) { cerr<<" "; for(int j=1;j<=m;j++)cerr<<arg[i][j]<<" "; cerr<<"\n"; } }
#define REP(i, a, b) for(int i = a; i <= b; ++i)
int n, m;
char g[1005][1005];
int dp1[1005][1005], dp2[1005][1005];
int stk1[1005], top;
int max1, max2;
void update(int val) {
if(val > max2)
max2 = val;
if(max2 > max1) {
int t = max2;
max2 = max1;
max1 = t;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d%d", &n, &m);
REP(i, 1, n) scanf("%s", g[i] + 1);
REP(j, 1, m) dp1[1][j] = (g[1][j] - '0');
REP(i, 2, n) REP(j, 1, m) dp1[i][j] = (g[i][j] - '0') ? (dp1[i - 1][j] + 1) : 0;
REP(i, 1, n) dp2[i][1] = 1;
REP(i, 1, n) REP(j, 2, m) dp2[i][j] = (dp1[i][j] <= dp1[i][j - 1]) ? (dp2[i][j - 1] + 1) : 1;
ERR2(dp1, n, m);
ERR2(dp2, n, m);
max1 = 0, max2 = 0;
REP(i, 1, n) {
top = 0;
REP(j, 1, m) {
while(top && dp1[i][stk1[top]] > dp1[i][j]) {
int h = dp1[i][stk1[top]];
int w = dp2[i][stk1[top]];
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
stk1[++top] = j;
}
while(top) {
int h = dp1[i][stk1[top]];
int w = dp2[i][stk1[top]];
if(w && h) {
update(w * h);
update((w - 1) *h);
update(w * (h - 1));
}
--top;
}
}
printf("%d\n", max2);
}
2019牛客暑期多校训练营(第二场) - H - Second Large Rectangle - dp的更多相关文章
- 2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)
题意:给出由01组成的矩阵,求求全是1的次大子矩阵. 思路: 单调栈 全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如: 1 0 0 1 ...
- 2020牛客暑期多校训练营 第二场 K Keyboard Free 积分 期望 数学
LINK:Keyboard Free 我要是会正经的做法 就有鬼了. 我的数学水平没那么高. 三个同心圆 三个动点 求围成三角形面积的期望. 不会告辞. 其实可以\(n^2\)枚举角度然后算出面积 近 ...
- 2020牛客暑期多校训练营 第二场 J Just Shuffle 置换 群论
LINK:Just Shuffle 比较怂群论 因为没怎么学过 置换也是刚理解. 这道题是 已知一个置换\(A\)求一个置换P 两个置换的关键为\(P^k=A\) 且k是一个大质数. 做法是李指导教我 ...
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- 2020牛客暑期多校训练营 第二场 C Cover the Tree 构造 贪心
LINK:Cover the Tree 最受挫的是这道题,以为很简单 当时什么都想不清楚. 先胡了一个树的直径乱搞的贪心 一直过不去.后来意识到这类似于最经典长链剖分优化贪心的做法 然后那个是求最大值 ...
- 2020牛客暑期多校训练营 第二场 B Boundary 计算几何 圆 已知三点求圆心
LINK:Boundary 计算几何确实是弱项 因为好多东西都不太会求 没有到很精通的地步. 做法很多,先说官方题解 其实就是枚举一个点 P 然后可以发现 再枚举一个点 然后再判断有多少个点在圆上显然 ...
- 2020牛客暑期多校训练营 第二场 A All with Pairs 字符串hash KMP
LINK:All with Pairs 那天下午打这个东西的时候状态极差 推这个东西都推了1个多小时 (比赛是中午考试的我很困 没睡觉直接开肝果然不爽 一开始看错匹配的位置了 以为是\(1-l\)和\ ...
- 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem
题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3 4 2 3 4 输出:0 0 1 题解: 认真想一 ...
- [题解] 2019牛客暑期多校第三场H题 Magic Line
题目链接:https://ac.nowcoder.com/acm/contest/883/H 题意:二维平面上有n个不同的点,构造一条直线把平面分成两个点数相同的部分. 题解:对这n个点以x为第一关键 ...
- 2020牛客暑假多校训练营 第二场 H Happy Triangle set 线段树 分类讨论
LINK:Happy Triangle 这道题很容易. 容易想到 a+b<x a<x<b x<a<b 其中等于的情况在第一个和第三个之中判一下即可. 前面两个容易想到se ...
随机推荐
- Sql Server 压缩数据库占用空间
1.删除数据库库中不必要的数据2. 在数据库上右击,任务,收缩,文件,在收缩操作上选择在未使用的空间前重新组织页,将文件收缩到的最后一行为最小为XXM,在前面的输入框中填入该值,然后点击确定3.分离该 ...
- Window Server 2008 R2 FTP服务用户隔离
Window Server 2008 R2 FTP服务用户隔离 原题:安装FTP服务,新建一个FTP站点,主目录为C:\ftproot,通过适当技术实现用户soft1 与soft2通过匿名方式登录FT ...
- mac os安裝jdk
下載安裝 打开mac笔记本,输入账号密码登陆后,点击桌面上的terminal终端图标.打开终端,然后在终端中输入命令java. 从下面的图中可以看到,终端会自动给出提示,没有可以使用的java命令 ...
- 四种会话跟踪技术以及jstl介绍
四种会话跟踪技术 page:代表与一个页面相关的对象和属性.一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示.这既包括 ...
- rocketmq架构设计
# 架构设计 1 技术架构 RocketMQ架构上主要分为四部分,如上图所示: Producer:消息发布的角色,支持分布式集群方式部署.Producer通过MQ的负载均衡模块选择相应的Broker集 ...
- linux运维、架构之路-网络基础
一. 常用网络设备 1.交换机:实现多台主机之间互相通讯的需求 交换机实现互相通讯的要求: ①主机身份标识信息:mac地址,利用源mac和目标mac地址,进行身份信息识别 ②主机通过交换机识别目标主机 ...
- eclipse 报错:One or more constraints have not been satisfied.
接受 我有同样的问题.在我的maven项目中添加速度依赖关系后,我在标记选项卡中得到相同的错误.然后我注意到maven项目创建的web.xml文件具有servlet2.3模式.当我将其更改为servl ...
- java文件断点上传
1,项目调研 因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 在GoogleCode上面,代码弄下来超级不方便,还是配置hosts才好,把代码重新上传到了github上面. http ...
- 移动端rem布局屏幕适配插件(放js中便可使用)
/* doc:不用管:document对象 win:不用管:window对象 design:注意:设计稿的尺寸/物理像素*/ (function (doc, win,design) {// alert ...
- Microsoft Office Word
快捷键 选区 选择块:[Shift]+click,光标放到块的一端,然后按住Shift,然后光标放到块的另一端. 更新域: F9 右键没有更新域选项时可以使用,如更新全部域先Ctrl + A然后F9 ...