Loading [MathJax]/jax/element/mml/optable/SuppMathOperators.js

BZOJ1345:[Baltic2007]序列问题

浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=1345

假设当前序列是单调的,那么显然答案就是从低往高合并的权值和。

假设a,那么合并a,b然后合并b,c的代价是b+c,显然要比合并b,c再合并a,c的代价c+c要优。

如果当前序列不单调,那么必然存在一个位置pos满足a[pos-1]\geqslant a[pos] \leqslant a[pos+1]。我们只需要把a[pos]a[pos-1],a[pos+1]中值较小的那个合并即可。可以证明,能与a[pos]合并的最小值就是min(a[pos-1],a[pos+1]),如果a[pos-1]或者a[pos+1]之前与其它数合并过,并且发生了改变,那么改变之后的数值显然是大于min(a[pos-1],a[pos+1])的。所以我们只需要维护一个单调栈,发现这种情况判断更新答案即可。最后会剩下一个单调递减的序列,我们再按照第一种情况处理就行。

时间复杂度:O(n)

空间复杂度:O(n)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn=1e6+5,inf=2e9+5;

ll ans;
int n,top;
int stk[maxn];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

int main() {
	n=read();
	stk[0]=inf;
	for(int i=1;i<=n;i++) {
		int x=read();
		while(top&&stk[top]<=x)
			ans+=min(stk[top-1],x),top--;
		stk[++top]=x;
	}
	top--;
	while(top)ans+=stk[top],top--;
	printf("%lld\n",ans);
	return 0;
}
posted @   AKMer  阅读(124)  评论(0编辑  收藏  举报
编辑推荐:
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示