优秀的分治题目。是“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)\),可知

\[\begin{aligned}\
[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\),对上式进行放缩,得

\[\begin{aligned}\\
[(-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【分治】【决策单调性】的更多相关文章

  1. CF868F Yet Another Minimization Problem 分治决策单调性优化DP

    题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...

  2. bzoj2216: [Poi2011]Lightning Conductor(分治决策单调性优化)

    每个pi要求 这个只需要正反DP(?)一次就行了,可以发现这个是有决策单调性的,用分治优化 #include<iostream> #include<cstring> #incl ...

  3. [BZOJ2739]最远点(DP+分治+决策单调性)

    根据旋转卡壳,当逆时针遍历点时,相应的最远点也逆时针转动,满足决策单调性.于是倍长成链,分治优化DP即可,复杂度O(n^2). #include<cstdio> #include<a ...

  4. BZOJ2739 最远点(分治 + 决策单调性)

    2739: 最远点 Time Limit: 20 Sec Memory Limit: 256 MB Description 给你一个N个点的凸多边形,求离每一个点最远的点. Input 本题有多组数据 ...

  5. 决策单调性&wqs二分

    其实是一个还算 trivial 的知识点吧--早在 2019 年我就接触过了,然鹅当时由于没认真学并没有把自己学懂,故今复学之( 1. 决策单调性 引入:在求解 DP 问题的过程中我们常常遇到这样的问 ...

  6. CodeForces 868F Yet Another Minimization Problem(决策单调性优化 + 分治)

    题意 给定一个序列 \(\{a_1, a_2, \cdots, a_n\}\),要把它分成恰好 \(k\) 个连续子序列. 每个连续子序列的费用是其中相同元素的对数,求所有划分中的费用之和的最小值. ...

  7. P2877 [USACO07JAN]牛校Cow School(01分数规划+决策单调性分治)

    P2877 [USACO07JAN]牛校Cow School 01分数规划是啥(转) 决策单调性分治,可以解决(不限于)一些你知道要用斜率优化却不会写的问题 怎么证明?可以暴力打表 我们用$ask(l ...

  8. 洛谷CF868F Yet Another Minimization Problem(动态规划,决策单调性,分治)

    洛谷题目传送门 貌似做所有的DP题都要先搞出暴力式子,再往正解上靠... 设\(f_{i,j}\)为前\(i\)个数分\(j\)段的最小花费,\(w_{l,r}\)为\([l,r]\)全在一段的费用. ...

  9. bzoj 2739 最远点——分治处理决策单调性

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2739 分治处理决策单调性的思想就是先找到一个询问,枚举所有可能的转移找到它的决策点,那么这个 ...

  10. 4951: [Wf2017]Money for Nothing 决策单调性 分治

    Bzoj4951:决策单调性 分治 国际惯例题面:一句话题面:供应商出货日期为Ei,售价为Pi:用户收购截止日期为Si,收购价格为Gi.我们要求max((Si-Ej)*(Gi-Pj)).显然如果我们把 ...

随机推荐

  1. SpringMVC听课笔记(五:处理模型数据)

    1. Spring MVC 提供了以下几种途径输出数据模型 -- ModelAndView: 处理方法返回值类型为ModelAndView 时,方法体即可通过该对象添加模型数据 -- Map及Mode ...

  2. JavaWeb——Cookie,Session学习汇总

    什么是Cookie Cookie的作用 安全性能 Cookie的语法 Cookie注意细节 Cookie实例练习 什么是会话Session Session语法 Session与浏览器窗口的关系 ses ...

  3. 解决java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/Pattern

    明明引入了这个,却提示没有 看下面文章: http://www.maocaoying.com/article/109

  4. jvm-本地方法接口

    什么是本地方法 简单地讲,一个Native Methodt是一个Java调用非Java代码的接囗.一个Native Method是这样一个Java方法:该方法的实现由非Java语言实现,比如C.这个特 ...

  5. NodeRED常用操作

    NodeRED常用操作 记录使用在云服务器操作NodeRED过程中常用的一些过程或方法 重启NodeRED 通过命令行重启 我的NodeRED在pm2的自启动管理下,因此使用pm2进行重启 pm2 r ...

  6. 用werkzeug实现一个简单的python web框架

    使用工具 Pycharm , Navicat , WebStorm等 使用库 Werkzeug用于实现框架的底层支撑,pymysql用于实现ORM,jinja2用于模板支持,json用于返回json数 ...

  7. 【bzoj 1202】[HNOI2005] 狡猾的商人(图论--带权并查集+前缀和)

    题意:一个账本记录了N个月以来的收入情况,现在有一个侦探员不同时间偷看到M段时间内的总收入,问这个账本是否为假账. 解法:带权并查集+前缀和.   判断账本真假是通过之前可算到的答案与当前读入的值是否 ...

  8. Strategic game POJ - 1463 树型dp

    //题意:就是你需要派最少的士兵来巡查每一条边.相当于求最少点覆盖,用最少的点将所有边都覆盖掉//题解://因为这是一棵树,所以对于每一条边的两个端点,肯定要至少有一个点需要放入士兵,那么对于x-&g ...

  9. HTTP的传输编码(Transfer-Encoding:chunked) / net::ERR_INVALID_CHUNKED_ENCODING

    https://blog.csdn.net/m0_37668842/article/details/89138733 https://www.cnblogs.com/jamesvoid/p/11297 ...

  10. 国产smartbits版本-minismb如何测试路由器III

    Minismb测试仪表是复刻smartbits的国产版本,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数和 ...