【BZOJ2228】[ZJOI2011]礼物(单调栈)

题面

BZOJ

洛谷

题解

如果这个玩意不是一个三维立方体,而是一个二维的矩形,让你在里面找一个最大正方形,那么全世界都会做。

丢到三维上?似乎区别也不是很大啦。

我们先把每一层一片一片的剖开考虑,预处理以某个位置为左上角的最大正方形边长。这个很容易求,可以用单调队列做到\(O(pqr)\)。接下来枚举某个左上角,把在每一层上的这个边长全部扣下来,形成一个序列。那么要求的就是最小值乘以选择的长度的最大值。这个东西显然还是可以单调队列求。

那么这样子复杂度就变成了\(O(pqr)\),再分别按照另外两维切片,就可以考虑出所有位置的答案了。

然而我想了半天怎么求以某个点为左上角的最大正方形,就像萝卜求助,然后被萝卜狠狠狠狠狠的批判了一番:“不就搞个变量扫一遍就好了吗?”,我“???”(智商掉线.jpg,最近智商已经没了,要找点智商了。)

大概是这样的:按照某一行来做,从左往右确定每一列的答案,暴力拓展最大的合法正方形,假设边长为\(N\),那么往右移一个位置的时候直接从\(N-1\)还是枚举就好了。我实在是太菜了,这都不会。

注意一下他这个字符串的读入顺序并不是\(pqr\),而是\(qpr\)。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 155
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
char g[MAX][MAX][MAX];
int s[MAX][MAX][MAX];
int n[MAX][MAX][MAX];
int p[MAX][MAX];
int L[MAX],R[MAX],Q[MAX],H,T;
int a,b,c,ans;
bool check(int b,int c,int x,int y,int N)
{
if(x+N-1>b||y+N-1>c)return false;
int xx=x+N-1,yy=y+N-1;
return p[xx][yy]-p[xx][y-1]-p[x-1][yy]+p[x-1][y-1]==N*N;
}
void Calc(int a,int b,int c)
{
for(int i=1;i<=a;++i)
{
for(int j=1;j<=b;++j)
for(int k=1;k<=c;++k)
p[j][k]=s[i][j][k]+p[j-1][k]+p[j][k-1]-p[j-1][k-1];
for(int j=1;j<=b;++j)
{
int N=0;
for(int k=1;k<=c;++k)
{
while(check(b,c,j,k,N+1))++N;
n[i][j][k]=N;N-=1;
}
}
}
for(int j=1;j<=b;++j)
for(int k=1;k<=c;++k)
{
T=0;
for(int i=1;i<=a;++i)
{
while(T&&n[Q[T]][j][k]>=n[i][j][k])--T;
L[i]=Q[T]+1;Q[++T]=i;
}
T=0;
for(int i=a;i>=1;--i)
{
while(T&&n[Q[T]][j][k]>=n[i][j][k])--T;
R[i]=T?Q[T]-1:a;Q[++T]=i;
}
for(int i=1;i<=a;++i)
ans=max(ans,n[i][j][k]*(R[i]-L[i]+1));
}
}
int main()
{
b=read();a=read();c=read();
for(int i=1;i<=a;++i)
for(int j=1;j<=b;++j)
scanf("%s",g[i][j]+1);
for(int i=1;i<=a;++i)
for(int j=1;j<=b;++j)
for(int k=1;k<=c;++k)
s[i][j][k]=(g[i][j][k]=='N');
Calc(a,b,c);
for(int i=1;i<=b;++i)
for(int j=1;j<=a;++j)
for(int k=1;k<=c;++k)
s[i][j][k]=(g[j][i][k]=='N');
Calc(b,a,c);
for(int i=1;i<=c;++i)
for(int j=1;j<=b;++j)
for(int k=1;k<=a;++k)
s[i][j][k]=(g[k][j][i]=='N');
Calc(c,b,a);
printf("%d\n",4*ans);
return 0;
}

【BZOJ2228】[ZJOI2011]礼物(单调栈)的更多相关文章

  1. bzoj2228[ZJOI2011]礼物(gift)

    据说联赛之前写题解可以涨RP 这题的输入格式半天没看懂-其实是有q层摞在一起,每一层大小都是p*r,依次输入q层的情况.那么首先我们枚举三种挖方块的姿势,分别使切出的方块的上面/前面/右面是正方形的面 ...

  2. 2015 UESTC 数据结构专题G题 秋实大哥去打工 单调栈

    秋实大哥去打工 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 Descr ...

  3. CDOJ 1069 秋实大哥去打工 单调栈 下标处理

    E - 秋实大哥去打工 Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%lld & %llu Submit St ...

  4. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  5. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  6. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  7. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

  8. bzoj1510: [POI2006]Kra-The Disks(单调栈)

    这道题可以O(n)解决,用二分还更慢一点 维护一个单调栈,模拟掉盘子的过程就行了 #include<stdio.h> #include<string.h> #include&l ...

  9. BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...

随机推荐

  1. 查看CentOS/Linux的版本信息

    今天在安装MySql的时候,想选择linux的版本对应的MySql. 1.查看内核版本和x86/x64版本 方法一.cat /proc/version [root@sxl129 Desktop]# c ...

  2. C# 如何物理删除有主外键约束的记录?存储过程实现

    十年河东,十年河西,莫欺少年穷 本篇主旨是如何物理删除有主外键约束的记录!那么,我们从主外键走起! 下面新建三张有主外键约束的表,分别为:系/学院表,专业班表,学生表,如下: CREATE TABLE ...

  3. 浅谈左偏树在OI中的应用

    Preface 可并堆,一个听起来很NB的数据结构,实际上比一般的堆就多了一个合并的操作. 考虑一般的堆合并时,当我们合并时只能暴力把一个堆里的元素一个一个插入另一个堆里,这样复杂度将达到\(\log ...

  4. Linux下部署Samba服务环境的操作记录

    关于Linux和Windows系统之间的文件传输,很多人选择使用FTP,相对较安全,但是有时还是会出现一些问题,比如上传文件时,文件名莫名出现乱码,文件大小改变等问题.相比较来说,使用Samba作为文 ...

  5. C. Oh Those Palindromes

    题意 给以一个字符串,让你重排列,使得回文子串的数目最多 分析 对于一个回文串,在其中加入一些字符并不会使回文子串的个数增加,所以对于相同的字符一起输出即可,我是直接排序 代码 #include< ...

  6. THE First Individual Project - Word frequency program

    第一次写博客,这次也是本学期写到第一个程序. 老师要求网址:http://www.cnblogs.com/jiel/p/3311400.html#2777556 一.项目预计时间 一开始想使用不熟悉的 ...

  7. 《Linux内核分析》第五周笔记 扒开系统调用的三层皮(下)

    扒开系统调用的三层皮(下) 一.给menuOS增加time和time-asm 通过内核调试系统调用.将上次做的实验加入到menusOS,变成menusOS里面的两个命令. 1 int Getpid(i ...

  8. first time to use github

    first time to use github and feeling good. 学习软件工程,老师要求我们用这个软件管理自己的代码,网站是全英的,软件也简单易用,方便 https://githu ...

  9. Junit4使用实验报告

    一.题目简介 Junit4的使用及求和测试. 二.源码的github链接 https://github.com/bjing123/test-/blob/master/Arithmetic.txt ht ...

  10. 剑指offer:字符串的排列

    题目描述: 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: ...