洛谷P1191 矩形 题解
笛卡尔树的介绍
笛卡尔树,是一种二叉搜索树,它满足如下条件:
- 每个节点的编号满足二叉搜索树的性质。
- 每个节点的权值满足小根堆或大根堆的性质。
大概是这个样子:
笛卡尔树的建树
笛卡尔树的用途
它可以用来解决区间最值问题,它有一个重要性质:当这个笛卡尔树为小根堆时,\(\min_{i = l}^r a_i = a_{\operatorname{lca}(l,r)}\),当这个笛卡尔树为大根堆时,\(\max_{i = l}^r a_i = a_{\operatorname{lca}(l,r)}\)。
所以,我们要求一个区间的最小值,只需将笛卡尔树建成小根堆的样式,按照性质求,如果要求一个区间的最大值,只需将笛卡尔树建成大根堆的样式,按照性质求。
当然,它还可以求有多少个区间的最小值或最大值为 \(a_i\),只需看有对少对区间的两端点的最近公共祖先是 \(i\) 即可,由于要使 \(\operatorname{lca}(l,r) = i\),那么 \(l\) 肯定在 \(i\) 的左子树或是 \(i\),\(r\) 肯定在 \(i\) 的右子树或是 \(i\),所以,设 \(s_i\) 表示 \(i\) 这个子树的大小,\(l_i\) 表示 \(i\) 的左儿子,\(r_i\) 表示 \(i\) 的右儿子,则就有 \((s_{l_i}+1) \times (s_{r_i}+1)\) 对区间的两端点的最近公共祖先为 \(i\)。
此题做法
首先使用前缀和将每个位置往上有多少个连续的 H,设这个数组为 \(f\)。
我们枚举每一行的每个位置。
然后放个假设图(其中一行):
图可能有点丑,请谅解(感谢)!!
假设这是第 \(K\) 行的 \(f\) 数组情况,其中第 \(i\) 个柱子的高度是 \(f_{K,i}\) 对于这第 \(K\) 行,如果要计算跟这个矩阵有关的矩阵有多少个,那么它必须得找高度比它高或相等的柱子拼起来才行,所以得找到最左边的一个柱子 \(j\),使得 \(j \le i\) 并且从 \(j\) 到 \(i\) 这些柱子的高度都大于等于等于柱子 \(i\) 的高度,那么这个 \(j\) 就是高为第 \(i\) 个柱子的矩形的最小左端点,然后再找到 \(k\),使得 \(k<i\) 并且从 \(i\) 到 \(k\) 这些柱子的高度都大于等于等于柱子 \(i\) 的高度,那么这个 \(k\) 就是高为第 \(i\) 个柱子的矩形的最大右端点,到这里大家都知道可以用单调栈做了吧,但是,我们是要用笛卡尔树的,所以还没完。实际上我们就是要找到区间长度最大的 \([j,k]\),使得 \(\min_{q = j}^k a_q = a_i\),那么就变成了上面说的笛卡尔树的用途的变形,由于我们要使 \([j,k]\) 的长度最大并且满足要求,那么 \(j\) 一定是 \(i\) 的左子树中编号最小的数(如果 \(i\) 没有左子树,那 \(j = i\)),\(k\) 一定是 \(i\) 的右子树中编号最大的数(如果 \(i\) 没有右子树,那 \(k = i\)),这样才能使 \([j,k]\) 长度最大且满足条件,知道了矩形最小左端点 \(j\) 和最大右端点 \(k\) 以及最大高度 \(f_{K,i}\),那 \((i-j+1) \times (k-i+1) \times f_{K,i}\) 就是包含第 \(i\) 个柱子的矩形个数,然后求一个子树中编号最小的数和编号最大的数只需找到笛卡尔树的根,然后搜索一下,递推即可。
时间复杂度可以说是题解区数一数二的了,\(O(n^2)\)。
讲的这么详细,放个代码没问题吧:
#include<bits/stdc++.h>
using namespace std;
const int N = 155;
char a[N][N];
int q[N];
int f[N][N];
int l[N];
int r[N];
int depmax[N];
int depmin[N];
int num[N];
void dfs(int x)
{
depmax[x] = x;
depmin[x] = x;
if(l[x])
{
dfs(l[x]);
depmin[x] = min(depmin[x],depmin[l[x]]);
depmax[x] = max(depmax[x],depmax[l[x]]);
}
if(r[x])
{
dfs(r[x]);
depmin[x] = min(depmin[x],depmin[r[x]]);
depmax[x] = max(depmax[x],depmax[r[x]]);
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
{
scanf("%s",a[i]+1);
}
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
if(a[i-1][j] == 'W'&&a[i][j] == 'W')
{
f[i][j] = f[i-1][j]+(a[i][j] == 'W');
}
else if(a[i][j] == 'W')
{
f[i][j] = 1;
}
}
}
int maxx = 0;
for(int i = 1;i<=n;i++)
{
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int t = 0;
for(int j = 1;j<=n;j++)
{
while(t&&f[i][q[t]]>f[i][j])
{
l[j] = q[t];
t--;
}
if(t)
{
r[q[t]] = j;
}
q[++t] = j;
}
for(int j = 1;j<=n;j++)
{
num[l[j]] = i;
num[r[j]] = i;
}
for(int j = 1;j<=n;j++)
{
if(num[j]!=i)
{
dfs(j);
break;
}
}
for(int j = 1;j<=n;j++)
{
int ll,rr;
if(l[j])
{
ll = min(depmin[l[j]],j);
}
else
{
ll = j;
}
if(r[j])
{
rr = max(depmax[r[j]],j);
}
else
{
rr = j;
}
maxx+=(j-ll+1)*(rr-j+1)*f[i][j];
}
}
printf("%d",maxx);
return 0;
}
洛谷P1191 矩形 题解的更多相关文章
- 洛谷 P1191 矩形 题解
P1191 矩形 题目描述 给出一个 \(n \times n\)的矩阵,矩阵中,有些格子被染成白色,有些格子被染成黑色,现要求矩阵中白色矩形的数量 输入格式 第一行,一个整数\(n\),表示矩形的大 ...
- 洛谷NOIp热身赛题解
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
- 洛谷P2827 蚯蚓 题解
洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...
- 洛谷P1816 忠诚 题解
洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...
- [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)
[POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...
- [NOI 2020 Online] 入门组T1 文具采购(洛谷 P6188)题解
原题传送门 题目部分:(来自于考试题面,经整理) [题目描述] 小明的班上共有 n 元班费,同学们准备使用班费集体购买 3 种物品: 1.圆规,每个 7 元. 2.笔,每支 4 元. 3.笔记本,每本 ...
- [洛谷P3948]数据结构 题解(差分)
[洛谷P3948]数据结构 Description 最开始的数组每个元素都是0 给出n,opt ,min,max,mod 在int范围内 A: L ,R ,X 表示把[l,R] 这个区间加上X(数组的 ...
- [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...
- 洛谷P1189 SEARCH 题解 迭代加深
题目链接:https://www.luogu.com.cn/problem/P1189 题目大意: 给你一个 \(n \times m\) 的矩阵,其中有一些格子可以走,一些各自不能走,然后有一个点是 ...
- 洛谷 P5221 Product 题解
原题链接 庆祝!第二道数论紫题. 推式子真是太有趣了! \[\prod_{i=1}^n \prod_{j=1}^n \frac{\operatorname{lcm}(i,j)}{\gcd(i,j)} ...
随机推荐
- 中电资讯-乘风破浪数字经济,银行如何Hold数据?
近期各类规划密集发布人行金融科技发展规划发布 金融标准化"十四五"规划发布 "十四五"信息化规划发布 -- 和数据应用有关的各项政策密集出炉 数字经济发展中如何 ...
- 实用干货分享 - Oracle数据库RPM部署指南
下载依赖和Oracle19c版本的RPM包 http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-dat ...
- 用 erlang 描述 tcc
Transaction 视为一个 Actor. start_transaction(Order) -> p1 = spawn(start_order(self, Order.subOrder1) ...
- 非root用户使用AntDeploy部署docker
AntDeploy这个东西非常好用,可以直接将.NET CORE的程序直接发布到docker,刚好我有这个需求,但是程序默认给的账户示例是root账户的,需要对于需要分散开发的同学来说,这个东西风险有 ...
- 【Python】【爬虫】【问题解决方案记录】调试输出存在数据,print在控制台确丢失数据
如下图,调试可以看到数据是完整的 但是print输出的,恰好丢失了中间的一大堆数据.对,下图打问号的地方应该是小说才对. 看代码可能看不出缺失内容,可视化看看 对吧,刚好缺失了小说. 后来我尝试用写文 ...
- Go设置GOPROXY国内加速
go env -w GOFLAGS=-buildvcs=false 在 Linux 或 macOS 上面 需要运行下面命令(或者,可以把以下命令写到 .bashrc 或 .bash_profile 文 ...
- Windows下如何在当前目录下,打开cmd命令窗口
方法一: 在当前目录下,按下shift + 鼠标右键,会出现"在此处打开命令窗口"的字样,然后点击即可. 方法二: 在该文件夹上,按下shift + 鼠标右键,会出现"在 ...
- 什么是 单点登录SSO?SSO工作原理
记住多个用户名和密码来访问不同网站和应用程序很麻烦.单点登录 (SSO) 允许用户使用一组凭证访问多个资源,从而消除了对多个用户 ID 和密码的需求. 没有 SSO 的世界 在没有 SSO 的情况下, ...
- Ant和Ivy集成部署和使用
Apache Ivy是专门用来管理项目的jar包依赖的.我们知道Maven已经有很出色的这方面的功能,如果你已经在使用Maven,就没必要使用Ivy了.但是其实Maven除了这方面功能,还有很多强大的 ...
- 2022 年万圣节 Github 彩蛋
记录每年 Github 万圣节彩蛋,也记录有来项目成长历程. 2022 万圣节彩蛋 2021 万圣节彩蛋 2020 万圣节彩蛋