题解里有各种神奇的算法,实际上我们用链表模拟一下就可以解决。。
读入数据后我们记录下其序号和代表的值,然后按值从小到大进行排序,再对序号从大到小进行左右比较操作(排序后左右差值绝对值较小的一个肯定是它之前天数内营业额减当天营业额绝对值最小的一个),把答案加上,再把左右数组更新。注意到1时只剩它一个了,这时候特判把序号为1的权值输出即可。
代码很乱。。。凑合看吧
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=33000;
int n;
ll sum=0;
struct node
{
ll w;
int id;
}a[maxn];
int l[maxn],r[maxn];
ll c[maxn];
bool cmp(const node &x,const node &y)
{
return x.w<y.w;
}
void search(int x)
{
if(x==1)
{
sum+=a[1].w;
return ;
}
sum+=min(abs(a[l[x]].w-a[x].w),abs(a[r[x]].w-a[x].w));
r[l[x]]=r[x];
l[r[x]]=l[x];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&c[i]);
a[i].id=i;
}
for(int i=1;i<=n;i++)
{
a[i].w=c[i];
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
l[a[i].id]=a[i-1].id;
r[a[i].id]=a[i+1].id;
}
for(int i=1;i<=n;i++)
{
a[i].w=c[i];
}
a[0].w=a[n+1].w=1e9;
for(int i=n;i>=1;i--)
{
search(i);
// for(int j=1;j<=n;j++)
// {
// cout<<l[j]<<' '<<r[j]<<endl;
// }
// cout<<sum<<endl;
}
printf("%lld",sum);
return 0;
}