• 【洛谷P4393】Sequence


    题目大意:给定一个长度为 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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    使用IMAGEMAGICK的CONVERT工具批量转换图片格式
    不同服务器数据库之间的数据操作
    mysql初始(6)
    Elasticsearch-基础介绍及索引原理分析
    PowerDesigner 生成C#实体模版代码
    Oracle 学习
    创建 sp
    2.7号出现的问题解决
    学习总结relative和absolute
    Sharepoint创建List
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10950324.html
Copyright © 2020-2023  润新知