30%的测试数据 n<=500;
50%的测试数据 n <= 20,000。
单调队列。
每个数一定是和他左右两边第一个比他大的那个数中较小的那一个合并,直接单调队列O(n)做。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define LL long long
#define inf 1000000005
#define M 1000000+5
using namespace std;
int a[M],q[M],n,s[M];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]),s[i]=inf;
q[1]=a[1];
int r=1;
for (int i=2;i<=n;i++)
{
while (r>=1&&a[i]>q[r])
r--;
if (r) s[i]=q[r];
while (r>=1&&q[r]==a[i])
r--;
q[++r]=a[i];
}
r=1;
q[1]=a[n];
for (int i=n-1;i;i--)
{
while (r>=1&&a[i]>q[r])
r--;
if (r) s[i]=min(s[i],q[r]);
while (r>=1&&q[r]==a[i])
r--;
q[++r]=a[i];
}
LL ans=0;
for (int i=1;i<=n;i++)
if (s[i]!=inf) ans+=s[i];
cout<<ans<<endl;
return 0;
}
【BZOJ 1345】 [Baltic2007]序列问题Sequence
原文:http://blog.csdn.net/regina8023/article/details/44806701