解题思路:本题解题思路主要有两种,一种是运用STL中的set,一种是用平衡树。
先来讲一下如何用set来实现,因为我们都知道set具有能够维护一个由相同元素组成的有序序列,但每个元素只能出现一次,当输入元素的时候,如果当前元素是第一个元素,那么答案直接加上该元素,如果不是第一个元素,利用set自带的lower_bound()函数找到第一个大于等于当前元素的数,然后我们还需要找到小于当前元素最大的数,如果说我们通过lower_bound()函数找到的数与当前元素的值不相等的话,那么找到的元素的上一个值就是小于当前元素的最大值了,当然如果找到的元素和当前元素恰好相等的话,那波动就是0了,可以直接不用管,因为加也是加0。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int N =3e5+10;
int n;
int a[N];
set<int>s;
set<int>::iterator k1,k2;
int main()
{
cin>>n;
cin>>a[1];
long long ans=a[1];
s.insert(192608170);//这里首先要往set里插入上下界,防止后面调用lower_bound()函数找大于等于当前数的最小数和小于当前数的最大数的时候发生边界问题
s.insert(-192608170);
s.insert(a[1]);
for(int i=2;i<=n;i++)
{
cin>>a[i];
int x=a[i];
k1=s.lower_bound(x);
if(*k1!=x)
{
k2=k1;
k2--;
ans+=min(abs(x-*k1),abs(x-*k2));
}
s.insert(a[i]);
}
cout<<ans<<endl;
return 0;
}
第二种做法就是用平衡树来做。在我的上一篇关于平衡树的博客中提到过平衡树的几个基本操作http://t.csdn.cn/GAuCkhttp://t.csdn.cn/GAuCk,这个题就相当于给我们一个数,让我们每次在插入一个数前,先找到小于等于当前数的最大值和大于等于当前数的最小值,求出与当前数的最小差值加入到答案中,然后再将这个数插入到平衡树中,相比于第一种做法代码要长了很多。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=4e5+10,INF=1e8;
struct node{
int l,r;
int key,val;
}tr[N];
int n,root,idx;
int get_node(int key)
{
tr[++idx].key=key;
tr[idx].val=rand();
return idx;
}
void zig(int &p)//右旋
{
int q=tr[p].l;
tr[p].l=tr[q].r;
tr[q].r=p;
p=q;
}
void zag(int &p)//左旋
{
int q=tr[p].r;
tr[p].r=tr[q].l;
tr[q].l=p;
p=q;
}
void build()
{
root=get_node(-INF);
tr[root].r=get_node(INF);
if(tr[tr[root].r].val>tr[root].val)
zag(root);
}
void insert(int &p,int key)
{
if(!p)
p=get_node(key);
if(tr[p].key==key)
return ;
if(tr[p].key>key)
{
insert(tr[p].l,key);
if(tr[tr[p].l].val>tr[p].val)
zig(p);
}
else
{
insert(tr[p].r,key);
if(tr[tr[p].r].val>tr[p].val)
zag(p);
}
}
int get_pre(int p,int key)//找到小于等于key的最大数
{
if(!p)
return -INF;
if(tr[p].key>key)
return get_pre(tr[p].l,key);
else
return max(tr[p].key,get_pre(tr[p].r,key));
}
int get_next(int p,int key)//找到大于等于key的最小数
{
if(!p)
return INF;
if(tr[p].key<key)
return get_next(tr[p].r,key);
else
return min(tr[p].key,get_next(tr[p].l,key));
}
int main()
{
cin>>n;
build();
long long res=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(i==1)
res+=x;
else
res+=min(x-get_pre(root,x),get_next(root,x)-x);
insert(root,x);
}
cout<<res<<endl;
return 0;
}