[bzoj1345]序列问题
记每一个数向比他大的数合并时的代价为这个数字的代价,显然除了最大值以外,每一个数都有一个代价,那么这个代价和就是最终答案
考虑最小化这个代价和,也就是让每一个数的代价最小,显然这个代价不会小于向左和右第一个比他大的数中较小的数,然后这样的方案也很好构造,这个东西用单调栈来处理即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 int n,a[N],lmx[N],rmx[N],s[N]; 5 long long ans; 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 9 memset(lmx,0x3f,sizeof(lmx)); 10 memset(rmx,0x3f,sizeof(rmx)); 11 for(int i=1;i<=n;i++){ 12 while ((s[0])&&(s[s[0]]<a[i]))s[0]--; 13 if (s[0])lmx[i]=s[s[0]]; 14 s[++s[0]]=a[i]; 15 } 16 s[0]=0; 17 for(int i=n;i;i--){ 18 while ((s[0])&&(s[s[0]]<a[i]))s[0]--; 19 if (s[0])rmx[i]=s[s[0]]; 20 s[++s[0]]=a[i]; 21 } 22 for(int i=1;i<=n;i++)ans+=min(lmx[i],rmx[i]); 23 printf("%lld",ans-0x3f3f3f3f); 24 }