CF102920L Two Buildings【分治】【决策单调性】
优秀的分治题目。是“2020-2021 ACM-ICPC, Asia Seoul Regional Contest”的一道题。
Description
There are \(n\) buildings along a horizontal street. The buildings are next to each other along the street, and the \(i\)-th building from left to right has width \(1\) and height \(h_i\). Among the \(n\) buildings, we are to find two buildings, say the \(i\)-th building and \(j\)-th building with \(i<j\), such that \((h_i+h_j)*(j−i)\) is maximized.
For example, the right figure shows \(5\) buildings, with heights \(1\), \(3\), \(2\), \(5\), \(4\), from left to right. If we choose the first \(2\) buildings, then we get \((1+3)*(2−1)=4\). If we choose the first and fifth buildings, then we \((1+4)*(5−1)=20\). The maximum value is achieved by the second and fifth buildings with heights \(3\) and \(4\), respectively: \((3+4)*(5−2)=21\).
Write a program that, given a sequence of building heights, prints \(\max_{1\le i<j\le n}(h_i+h_j)*(j−i)\).
Input
Your program is to read from standard input. The input starts with a line containing an integer \(n\) (\(2\le n\le 1,000,000\)), where \(n\) is the number of buildings. The buildings are numbered \(1\) to \(n\) from left to right. The second line contains the heights of \(n\) buildings separated by a space such that the \(i\)-th number is the height \(h_i\) of the \(i\)-th building (\(1\le h_i\le 1,000,000\)).
Output
Your program is to write to standard output. Print exactly one line. The line should contain \(\max_{1\le i<j\le n}(h_i+h_j)*(j−i)\).
Examples
input
5
1 3 2 5 4
output
21
input
5
8 3 6 3 1
output
36
题意:
有 \(n(2\le n\le 1000000)\) 栋楼房,第 \(i\) 栋高度为 \(h_i(1\le h_1\le 1000000)\)。问两栋楼房所能构成的 \((h_i+h_j)*(j−i)\) 最大值是多少。
题解:
为了方便,我们把要求的式子转化为 \((h_i-(-h_j))\times(j-i)\),这样构造出数列 \(-h_i\),就是坐标系中 \(x\) 轴上方和 \(x\) 轴下方两个数列中选出两个 \(h\) 进行计算。
如果存在 \(i<j\),同时 \(-h_i<-h_j\),那么 \(j\) 一定比 \(i\) 更优。可以用单调栈来把数列 \(\{h_i\}\) 和 \(\{-h_i\}\) 都变为单调的。得到单增的 \(\{H_i\}\) 和 \(\{-H_i\}\)。

如图,图中橙色的点删除后,对答案产生贡献的点只会在蓝色中产生。
而蓝色的点 \(\{H_i\}\) 和 \(\{-H_i\}\) 对应了两段递增的序列(此时下标 \(i\) 不一定连续)。最终答案为 \([H_i-(-H_j)]\times(j-i)\)。假设对于选定的 \(H_i\),对应 \(-H_j\) 为最优解,即 \(\forall k>j,[H_i-(-H_j)]\times(j-i)\geqslant[H_i-(-H_k)]\times(k-i)\),可知
[H_i-(-H_j)]\times(j-i)&\geqslant[H_i-(-H_k)]\times(k-i)\\\
[H_i-(-H_j)]\times(j-i)\color{red}{-[H_i-(-H_k)]\times(j-i)}&\geqslant[H_i-(-H_k)]\times(k-i)\color{red}{-[H_i-(-H_k)]\times(j-i)}\\\
[(-H_k)-(-H_j)]\times(j-i)&\geqslant[H_i-(-H_k)]\times(k-j)
\end{aligned}\]
因此对于 \(l<i\),对上式进行放缩,得
[(-H_k)-(-H_j)]\times(j-i)&\geqslant[H_i-(-H_k)]\times(k-j)\\\
[(-H_k)-(-H_j)]\times(j-i)\color{blue}{+[(-H_k)-(-H_j)]\times(i-l)}&\geqslant[H_i-(-H_k)]\times(k-j)\color{red}{-(H_i-H_l)\times(k-j)}\\\
[(-H_k)-(-H_j)]\times(j-l)&\geqslant[H_l-(-H_k)]\times(k-j)\\\
[(-H_k)-(-H_j)]\times(j-l)\color{blue}{+[H_l-(-H_k)]\times(j-l)}&\geqslant[H_l-(-H_k)]\times(k-j)\color{blue}{+[H_l-(-H_k)]\times(j-l)}\\\
[H_l-(-H_j)]\times(j-l)&\geqslant[H_l-(-H_k)]\times(k-l)
\end{aligned}\]
所以当 \(H_i\) 对应的最优解位置为 \(-H_j\) 时,\(l<i\) 的 \(H_l\) 对应的最优解位置 \(-H_k\) 满足 \(k\geqslant j\)。
如果上式推导过于复杂,它对应的图形推导如下。

左图中,如果 \(H_i\) 对应的最优解是 \(H_j\),那么①的面积 \(S_1\) 一定比②的 \(S_2\) 大。右图中,那么对 \(l<i\),已知 \(S_1\geqslant S_2\),有 \(S_1+S_3\geqslant S_2-S_4\),所以 \(l\) 对应的最优解一定不会在 \(j\) 右边。
此时再考虑上边的推导,便能清楚理解了。
分治递归,时间复杂度为 \(O(n\log n)\)。
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
int a[1001000],b[1001000],c[1001000];
int bp[1001000],cp[1001000];
ll ans=0;
void solve(int l,int r,int L,int R)
{
if(l>r)
return;
int mid=(l+r)>>1,q=0;
ll Ans=0;
for(int i=L;i<=R;++i)
{
if(Ans<1ll*(cp[i]-bp[mid])*(b[mid]+c[i]))
{
q=i;
Ans=1ll*(cp[i]-bp[mid])*(b[mid]+c[i]);
}
}
ans=ans>Ans?ans:Ans;
solve(l,mid-1,L,q);
solve(mid+1,r,q,R);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
int ii=0,iii=0;
c[0]=1e8;
for(int i=1;i<=n;++i)
{
if(a[i]>b[ii])
{
b[++ii]=a[i];
bp[ii]=i;
}
while(a[i]>=c[iii])
--iii;
c[++iii]=a[i];
cp[iii]=i;
}
solve(1,ii,1,iii);
printf("%lld\n",ans);
return 0;
}
CF102920L Two Buildings【分治】【决策单调性】的更多相关文章
- CF868F Yet Another Minimization Problem 分治决策单调性优化DP
题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...
- bzoj2216: [Poi2011]Lightning Conductor(分治决策单调性优化)
每个pi要求 这个只需要正反DP(?)一次就行了,可以发现这个是有决策单调性的,用分治优化 #include<iostream> #include<cstring> #incl ...
- [BZOJ2739]最远点(DP+分治+决策单调性)
根据旋转卡壳,当逆时针遍历点时,相应的最远点也逆时针转动,满足决策单调性.于是倍长成链,分治优化DP即可,复杂度O(n^2). #include<cstdio> #include<a ...
- BZOJ2739 最远点(分治 + 决策单调性)
2739: 最远点 Time Limit: 20 Sec Memory Limit: 256 MB Description 给你一个N个点的凸多边形,求离每一个点最远的点. Input 本题有多组数据 ...
- 决策单调性&wqs二分
其实是一个还算 trivial 的知识点吧--早在 2019 年我就接触过了,然鹅当时由于没认真学并没有把自己学懂,故今复学之( 1. 决策单调性 引入:在求解 DP 问题的过程中我们常常遇到这样的问 ...
- CodeForces 868F Yet Another Minimization Problem(决策单调性优化 + 分治)
题意 给定一个序列 \(\{a_1, a_2, \cdots, a_n\}\),要把它分成恰好 \(k\) 个连续子序列. 每个连续子序列的费用是其中相同元素的对数,求所有划分中的费用之和的最小值. ...
- P2877 [USACO07JAN]牛校Cow School(01分数规划+决策单调性分治)
P2877 [USACO07JAN]牛校Cow School 01分数规划是啥(转) 决策单调性分治,可以解决(不限于)一些你知道要用斜率优化却不会写的问题 怎么证明?可以暴力打表 我们用$ask(l ...
- 洛谷CF868F Yet Another Minimization Problem(动态规划,决策单调性,分治)
洛谷题目传送门 貌似做所有的DP题都要先搞出暴力式子,再往正解上靠... 设\(f_{i,j}\)为前\(i\)个数分\(j\)段的最小花费,\(w_{l,r}\)为\([l,r]\)全在一段的费用. ...
- bzoj 2739 最远点——分治处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2739 分治处理决策单调性的思想就是先找到一个询问,枚举所有可能的转移找到它的决策点,那么这个 ...
- 4951: [Wf2017]Money for Nothing 决策单调性 分治
Bzoj4951:决策单调性 分治 国际惯例题面:一句话题面:供应商出货日期为Ei,售价为Pi:用户收购截止日期为Si,收购价格为Gi.我们要求max((Si-Ej)*(Gi-Pj)).显然如果我们把 ...
随机推荐
- XCTF-你是谁
前期工作 查壳,无.运行 不知道有啥用,迷宫题? 逆向分析 文件结构 查看了一下主要逻辑在background中,因为MainActivity的setContentView是background.ba ...
- 大型面试现场:一条update sql执行都经历什么?
导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 24 篇. 今天我要跟你分享的MySQL话题是:"从一条update sql执行都经历什么开始,发散开一系列的问题,看看你能抗到第几 ...
- Spark练习之wordcount,基于排序机制的wordcount
Spark练习之wordcount 一.原理及其剖析 二.pom.xml 三.使用Java进行spark的wordcount练习 四.使用scala进行spark的wordcount练习 五.基于排序 ...
- 封装打包Python脚本
1.前言 封装打包Python的好处,节省了安装各种各样包依赖的问题,同时可以加强我们代码隐私的安全性,这里我的演示环境是Python3.6 ,CentOS7的系统,同时打包工具采用pyinstall ...
- 从零搭建一个IdentityServer——聊聊Asp.net core中的身份验证与授权
OpenIDConnect是一个身份验证服务,而Oauth2.0是一个授权框架,在前面几篇文章里通过IdentityServer4实现了基于Oauth2.0的客户端证书(Client_Credenti ...
- cassandra权威指南读书笔记--cassandra概述
cassandra是一个开源的.分布式.去中心化.弹性可扩展.高可用.容错.可调一致性.面向行数据库,分布式设计基于Amazon Dynamo,数据模型基于Google BigTable.cassan ...
- Codeforces Round #690 (Div. 3) E2. Close Tuples (hard version) (数学,组合数)
题意:给你一长度为\(n\)的序列(可能含有相等元素),你要找到\(m\)个位置不同的元素使得\(max(a_{i-1},a_{i_2},...,a_{i_m})-min(a_{i-1},a_{i_2 ...
- Codeforces Round #649 (Div. 2) B. Most socially-distanced subsequence (数学,差分)
题意:有一长度为\(n\)的数组,求一子序列,要求子序列中两两差的绝对值最大,并且子序列尽可能短. 题解:将数组看成坐标轴上的点,其实就是求每个单调区间的端点,用差分数组来判断单调性. 代码: #in ...
- Codeforces Round #655 (Div. 2) A. Omkar and Completion (构造)
题意:构造一个长度为\(n\)的序列,要求所有元素总和不大于\(1000\),并且任意两项的和不等于另外一项. 题解:全构造\(1\)就好了. 代码: int t; int n; int main() ...
- Verilog hdl 实现单周期cpu
参考计组实验测试指令 - 简书,添加了一些细节. 1.添加 bne指令 修改 ctrl.v 之后修改mipstestloopjal_sim.asm,mars dump 为 bnetest. ...