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)).显然如果我们把 ...
随机推荐
- python atexit模块学习
python atexit模块 只定义了一个register模块用于注册程序退出时的回调函数,我们可以在这个函数中做一下资源清理的操作 注:如果程序是非正常crash,或者通过os._exit()退出 ...
- jQuery——样式与动画
通过jQuery,不仅能够轻松地为页面操作添加简单的视觉效果,甚至能创建更精致的动画. ###修改内联CSS jQuery提供了.css()方法. 这个方法集getter(获取方法)和setter(设 ...
- 小米和MAC触摸板手势汇总
小米的触摸手势: 左键:单指单击 右键:双指单击 选取并打开:单指双击 滚动页面:双指 移动 拖拽项目:双击并拖拽 放大/缩小:双指张开,双指捏合 MAC触摸板手势: http://www.cr173 ...
- sql,关键字使用
select instr('dds万','万',1) from dual --判断万关键字是否存在 select to_single_byte('9') from dual --全角数字转为半角数字 ...
- IP路由__静态路由
1.静态路由的优缺点: 优点:对于路由器的CPU没有管理性开销,它意味着如果你不使用动态路由选择的话,你可能应该购买更为便宜的路由器.在路由器之间没有带宽占用,它意味着在WAN链接中你可以节省更多的钱 ...
- 国产App为什么如此“臃肿”?!
引言 App是Application的简称,正是因为有了丰富多彩的各类App,人们就可以通过它们来最大限度地发挥手中设备的功能.本文主要讨论手机上的App,因为手机的硬件和软件与十余年前相比早已有了巨 ...
- 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)(9/11)
$$2017-2018\ ACM-ICPC\ German\ Collegiate\ Programming\ Contest (GCPC 2017)$$ \(A.Drawing\ Borders\) ...
- priority_queue()大根堆和小根堆(二叉堆)
#include<iostream> #include <queue> using namespace std; int main() { //对于基础类型 默认是大顶堆 pr ...
- 2019牛客多校 Round8
Solved:3 Rank:261 E Explorer (线段树) 题意:n个点 m条边 每条边只有身高l,r内的人可以穿过 问有几种身高可以从1走到n 题解:把l,r离散化后(左闭右开) 线段树叶 ...
- LA3902 Network (树上dfs)
题目链接:点击打开链接 题意:n台机器连成一个树状网络,其中叶节点是客户端,其他节点是服务器,目前有一台服务器s正在提供服务.让你在其他服务器上也安排同样的服务,使得每台客户端到最近服务器的距离不超过 ...