• BZOJ1345:[Baltic2007]序列问题


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

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

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

    假设(aleqslant b leqslant c),那么合并(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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Ambari 整体架构
    Ambari 介绍
    xcode工程命令行生成ipa安装包
    gradle打包java项目
    FreeMarker标签介绍
    P与NP,从概念到研究全面综述
    计算机领域经典笑话
    自己动手写GC
    编程语言简史
    不第后赋菊
  • 原文地址:https://www.cnblogs.com/AKMer/p/10284357.html
Copyright © 2020-2023  润新知