怎么题解全是 dp?可以用笛卡尔树啊!

题目传送门。

笛卡尔树的介绍

笛卡尔树,是一种二叉搜索树,它满足如下条件:

  • 每个节点的编号满足二叉搜索树的性质。
  • 每个节点的权值满足小根堆或大根堆的性质。

大概是这个样子:

笛卡尔树的建树

请看这里。

笛卡尔树的用途

它可以用来解决区间最值问题,它有一个重要性质:当这个笛卡尔树为小根堆时,\(\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]\) 的长度之后,直接拿长度乘上当前柱子就是以当前柱子为高的最大矩形面积。然后求一个子树中编号最小的数和编号最大的数只需找到笛卡尔树的根,然后搜索一下,递推即可。

讲的这么详细,放个代码没问题吧:

#include<bits/stdc++.h>
using namespace std;
const int N = 4e3+5;
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];
//计算depmax,depmin
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()
{
while(1)
{
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
int n,m,k;
scanf("%d %d",&n,&m);
if(!n&&!m)
{
return 0;
}
scanf("%d",&k);
for(int i = 1;i<=n;i++)
{
scanf("%s",a[i]+1);
}
//求前缀和f
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
if(a[i-1][j] == 'H'&&a[i][j] == 'H')
{
f[i][j] = f[i-1][j]+(a[i][j] == 'H');
}
else if(a[i][j] == 'H')
{
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<=m;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<=m;j++)
{
num[l[j]] = i;//记录下这个点有父亲
num[r[j]] = i;//记录下这个点有父亲
}
for(int j = 1;j<=m;j++)
{
if(num[j]!=i)//如果这个点没有父亲
{
dfs(j);
break;
}
}
//计算
for(int j = 1;j<=m;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 = max(maxx,(rr-ll+1)*f[i][j]);
}
}
printf("%lld\n",1ll*maxx*k);
}
return 0;
}

题解:SP6517 JOCHEF - Farmer Sepp的更多相关文章

  1. usaco training 4.2.2 The Perfect Stall 最佳牛栏 题解

    The Perfect Stall题解 Hal Burch Farmer John completed his new barn just last week, complete with all t ...

  2. usaco training 4.1.1 麦香牛块 题解

    Beef McNuggets题解 Hubert Chen Farmer Brown's cows are up in arms, having heard that McDonalds is cons ...

  3. POJ 3279(Fliptile)题解

    以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...

  4. usaco training 4.1.3 fence6 题解

    Fence Loops题解 The fences that surround Farmer Brown's collection of pastures have gotten out of cont ...

  5. usaco training 4.1.2 Fence Rails 题解

    Fence Rails题解 Burch, Kolstad, and Schrijvers Farmer John is trying to erect a fence around part of h ...

  6. usaco training 3.4.3 fence9 题解

    Electric Fence题解 Don Piele In this problem, `lattice points' in the plane are points with integer co ...

  7. usaco 2002 月赛 Fiber Communications 题解

    Description Farmer John wants to connect his N (1 <= N <= 1,000) barns (numbered 1..N) with a ...

  8. 洛谷P2891 Dining P1402 酒店之王【类二分图匹配】题解+代码

    洛谷P2891 Dining P1402 酒店之王[类二分图匹配]题解+代码 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的 ...

  9. 题解——洛谷P1550 [USACO08OCT]打井Watering Hole(最小生成树,建图)

    题面 题目背景 John的农场缺水了!!! 题目描述 Farmer John has decided to bring water to his N (1 <= N <= 300) pas ...

  10. Codeforces Round #102 (Div. 1) A. Help Farmer 暴力分解

    A. Help Farmer 题目连接: http://www.codeforces.com/contest/142/problem/A Description Once upon a time in ...

随机推荐

  1. js 进制转换:十六进制转十进制、十进制转十六进制、十六进制转ASCII码、

    因为近期做小程序,蓝牙连接硬件,需要根据module bus通信协议解析数据,用到了很多标题的算法转换,借此总结一下. 十六进制 转 十进制 function hex2dec(hex) { var l ...

  2. Flutter问题 Flutter MissingPluginException(No implementation found for method xxx on channel xxx)

    问题如题 有时候项目跑着跑着突然控制台就报了这个错,用hot restart也没有用,问题的本质是plugin没有找到,这时候有两种方法 flutter clean,会将依赖清除,这时候再重新pub ...

  3. JVM简介—1.Java内存区域

    大纲 1.运行时数据区的介绍 2.运行时数据区各区域的作用 3.各个版本内存区域的变化 4.直接内存的使用和作用 5.站在线程的角度看Java内存区域 6.深入分析堆和栈的区别 7.方法的出入栈和栈上 ...

  4. Centos yum命令提示failed to set locale, defaulting to C

    目录 问题 locale提示 解决方案 问题 在输入yum命令是出现 Failed to set locale, defaulting to C 1 出现这个问题是由于系统没有正确设置locale环境 ...

  5. Qt编写安防视频监控系统58-子模块2窗口信息

    一.前言 窗口信息一般用来打印输出文字信息,带时间,有些用户场景可能除了时间和内容以外,还需要其他的字段信息,可以自行在代码中增加字段即可,窗口信息一般以表格样式居多,上面是字段标题,下面是一行行的输 ...

  6. Qt编写地图综合应用18-地图模式

    一.前言 除了传统的街道图地图外,默认的一般都是街道图,还有卫星图.三维图等,其中又有叠加层,比如叠加路况图层和路网图层等,最近去了多家的地图官网看对应的api接口,总体上感觉现在都往2.5D或者3D ...

  7. Qt编写项目作品27-多线程文件传输

    一.功能特点 多线程收发文件,支持加密传输. 接收端支持监听端口接收文件和主动连接服务器接收文件两种方式. 按照 文件开始符+文件大小+文件内容+文件结束符 逐个分包接收. 可对接收的加密过的文件包进 ...

  8. 《Hough变换及其在信息处理中的应用》电子书下载

    <Hough变换及其在信息处理中的应用>电子书下载:百度云盘,  提取码:9zyi

  9. 并发和并行 | Python中实现多线程 threading 和多进程 multiprocessing

    并发和并行 | Python中实现多线程 threading 和多进程 multiprocessing 昨天晚上组会轮到我汇报技术内容,最近正在和 ray 以及 spark 打交道,索性讲一下并发和并 ...

  10. Solution -「ZJOI 2015」「洛谷 P3343」地震后的幻想乡

    \(\mathscr{Description}\)   Link.   给定连通图简单无向 \(G=(V,E)\),对于 \(e\in E\),有边权 \(t_e\) 独立均匀随机生成自 \([0,1 ...