题目大意:给定一个长度为 N 的序列,每次可以合并相邻的两个元素,代价是两者中较大的值,合并之后的值也为两者较大的值,求合并 N-1 次后的最小代价是多少。

题解:

除了最大值以外,每个值均只会被合并一次,合并的代价一定是这个值左边最大值和右边最大值中较小的那一个。问题转化成了如何求解每个元素左边和右边第一个大于该元素的值,单调栈扫一遍即可。

注意:如果有相同的元素,如4 2 2 3,中间两个 2 在最后计算答案时会产生错误,避免的方式是计算每个元素右边的值取大于等于,左边取大于即可。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int inf=0x3f3f3f3f;
typedef long long LL; int n,a[maxn],l[maxn],r[maxn],stk[maxn],top;
LL ans; int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]); a[0]=a[n+1]=inf;
for(int i=1;i<=n+1;i++){
while(top&&a[stk[top]]<=a[i])r[stk[top--]]=i;
stk[++top]=i;
}
top=0;
for(int i=n;~i;i--){
while(top&&a[stk[top]]<a[i])l[stk[top--]]=i;
stk[++top]=i;
}
for(int i=1;i<=n;i++){
if(l[i]<1&&r[i]>n)continue;
if(l[i]>=1&&r[i]<=n)ans+=min(a[l[i]],a[r[i]]);
else if(r[i]>n)ans+=a[l[i]];
else if(l[i]<1)ans+=a[r[i]];
}
printf("%lld\n",ans);
return 0;
}

最新文章

  1. CSS布局——居中
  2. UI学习笔记---第七天
  3. vnextcn
  4. 【动态规划】流水作业调度问题与Johnson法则
  5. 【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)
  6. Amoeba for MySQL 非常好用的mysql集群软件
  7. 【HDU1514】Stars(树状数组)
  8. 构建安全的Xml Web Service系列之SSL篇
  9. selenium之handle学习 多窗口、句柄
  10. hdu 3829 Cat VS Dog 二分匹配 最大独立点集
  11. TeamForge使用指南
  12. Spring Boot 指定某个依赖的版本
  13. 也谈开源GIS架构实现思想
  14. oracle 数据库中某个字段逗号分隔,得到对应列中的个数(列转行)实现方法
  15. Android开发 静态static类与static方法持有Context是否导致内存泄露的疑问
  16. [NewLife.XCode]反向工程(自动建表建库大杀器)
  17. 如何开始DDD(续)
  18. iOS网络请求安全认证(JWT,RSA)
  19. Database学习 - mysql 数据库 数据操作
  20. 第二阶段——个人工作总结DAY09

热门文章

  1. flutter column row布局的列表自适应宽高
  2. Ajax中Put和Delete请求传递参数无效的解决方法(Restful风格)
  3. 我非要捅穿这 Neutron(一)网络实现模型篇
  4. Python学习笔记:(十二)输入输出
  5. harbor仓库安装
  6. Hibernate框架 初识 ORM概念
  7. jquery实现分页效果
  8. 【HTTP】二、HTTP协议的报文结构
  9. CentOS安装Netdata进行系统监控
  10. poj3191(负进位制)