BZOJ1345:[Baltic2007]序列問題
阿新 • • 發佈:2019-01-17
com www. bzoj ref ble 序列 最小 sla 情況 。我們只需要把\(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])\)的。所以我們只需要維護一個單調棧,發現這種情況判斷更新答案即可。最後會剩下一個單調遞減的序列,我們再按照第一種情況處理就行。
淺談棧:https://www.cnblogs.com/AKMer/p/10278222.html
題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=1345
假設當前序列是單調的,那麽顯然答案就是從低往高合並的權值和。
假設\(a\leqslant 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]\)
時間復雜度:\(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; }
BZOJ1345:[Baltic2007]序列問題