满分做法:
有一个专门解决这类问题的算法叫:GarsiaWachs算法。
算法流程:1.从序列开头往后找第一个位置(i)满足(a[i]<=a[i+2])的点(在这里我们令(a[n+1])和(a[0])为正无穷)。
2.将(a[i])和(a[i+1])合并,并删除原来的两个数,后面自动补齐。
3.从(i-1)位置向前扫,找到第一个位置(j)满足(a[j]>=a[i]+a[i+1]),并把合并的值插入到(j)后面。
这样复杂度就降到了(n²),用vector就可以达到(nlogn)了。(可以用平衡树优化,但我不会┭┮﹏┭┮)。
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxm=40007;
typedef long long ll;
int n;
vector<ll> a;
ll ans=0;
ll work()
{
int k=a.size()-2;
for(int i=0;i<=(int)a.size()-3;i++)//vector好像不能越界,i<=a.size()-3是错的,i<a.size()-2就对了
{
if(a[i]<=a[i+2])
{
k=i;
break;
}
}
ll tmp=a[k]+a[k+1];
a.erase(a.begin()+k);//删除K
a.erase(a.begin()+k);//由于数组已经向左移了一个了,因此之前的A[k+1]跑到了A[k]的位置上,所以还是删除A[k]
int pos=-1;
for(int i=k-1;i>=0;i--)
{
if(a[i]>tmp)
{
pos=i;
break;
}
}
a.insert(a.begin()+pos+1,tmp);
return tmp;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
ll x;
scanf("%lld",&x);
a.push_back(x);
}
for(int i=1;i<=n-1;i++)
{
ans+=work();
}
printf("%lld
",ans);
return 0;
}