[bzoj1345]序列问题

记每一个数向比他大的数合并时的代价为这个数字的代价,显然除了最大值以外,每一个数都有一个代价,那么这个代价和就是最终答案
考虑最小化这个代价和,也就是让每一个数的代价最小,显然这个代价不会小于向左和右第一个比他大的数中较小的数,然后这样的方案也很好构造,这个东西用单调栈来处理即可

 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 } 
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11846522.html