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