思路:
利用treap树的两个操作,一个是查找大于x的最小数,一个是查找小于x的最大数,将代码稍微修改一下就是大于等于和小于等于。
具体的所有操作解释都在这Treap树的基本操作以及模板题目_北岭山脚鼠鼠的博客-CSDN博客
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=33300,INF=1e7;
struct node
{
int l,r;
int val;
int key;
}tr[N];
int idx,root,n;
int get_node(int key)
{
tr[++idx].key=key;
tr[idx].val=rand();
return idx;
}
void build()
{
get_node(-INF);
get_node(INF);
root=1;
tr[1].r=2;
}
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 insert(int &p,int key)
{
if(!p) p=get_node(key);
else if(tr[p].key==key)return;
else if(tr[p].key>key)
{
insert(tr[p].l,key);
if(tr[tr[p].l].val) zig(p);
}else
{
insert(tr[p].r,key);
if(tr[tr[p].r].val>tr[p].val) zag(p);
}
}
int get_prev(int p,int key)
{
if(!p) return -INF;
if(tr[p].key >key) return get_prev(tr[p].l,key);
return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int p,int key)
{
if(!p) return INF;
if(tr[p].key<key) return get_next(tr[p].r,key);
return min(tr[p].key,get_next(tr[p].l,key));
}
int main()
{
build();
scanf("%d",&n);
ll sum=0;
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(i==1)
{
insert(root,x);
sum+=x;
}else
{
int a=get_next(root,x);
int b=get_prev(root,x);
sum+=min(abs(a-x),abs(b-x));
insert(root,x);
}
}
printf("%lld",sum);
return 0;
}