BZOJ1588
http://www.lydsy.com/JudgeOnline/problem.php?id=1588
splay维护一下前驱后继
#include<cstdio>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
inline int min(int a,int b){
return a<b?a:b;
}
const int N=100011,inf=(1<<30);
int num1,num2;
int n,x,ans;
namespace Splay{
int sz,rt;
int to[N][2],fa[N],num[N];
inline void rotate(int x,int &k){
register int y=fa[x],z=fa[y],l,r;
l=(x==to[y][0]?0:1);r=l^1;
if(y==k)
k=x;
else
to[z][0]==y?to[z][0]=x:to[z][1]=y;
fa[x]=z;fa[y]=x;fa[to[x][r]]=y;
to[y][l]=to[x][r];to[x][r]=y;
}
inline void modify(int x,int &k){
register int y,z;
while(x!=k){
y=fa[x];z=fa[y];
if(y!=k)((to[y][0]==x)^(to[z][0]==y))?rotate(x,k):rotate(y,k);
rotate(x,k);
}
}
inline void insert(int &k,int x,int father=0){
if(!k){
k=++sz;
fa[k]=father;
num[k]=x;
modify(k,rt);
return ;
}
x<num[k]?insert(to[k][0],x,k):insert(to[k][1],x,k);
}
inline void ask_before(int k,int x){
if(!k)return;
if(num[k]<=x){
num1=num[k];
ask_before(to[k][1],x);
}
else
ask_before(to[k][0],x);
}
inline void ask_after(int k,int x){
if(!k)return;
if(num[k]>=x){
num2=num[k];
ask_after(to[k][0],x);
}
else
ask_after(to[k][1],x);
}
}
using namespace Splay;
int main(){
scanf("%d",&n);
FOR(i,1,n){
num1=-inf;num2=inf;
scanf("%d",&x);
ask_after(rt,x);
ask_before(rt,x);
ans+=(i!=1?min(num2-x,x-num1):x);
insert(rt,x);
}
printf("%d",ans);
return 0;
}
或者写棵值域线段树冷静一下
#include<cstdio>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define gc getchar()
using namespace std;
const int N=400011,inf=1e9;
int n,pos,ans;
int a[N],b[N];
inline int min(int a,int b){
return a<b?a:b;
}
namespace Segment_Tree{
int tr[N];
inline int query_rank(int x,int k=1,int l=1,int r=40000){
++tr[k];
if(l==r)return 1;
int mid=(l+r)>>1;
return x<=mid?query_rank(x,ls):(tr[k<<1]+query_rank(x,rs));
}
inline int query_num(int x,int k=1,int l=1,int r=40000){
if(l==r)return l;
int mid=(l+r)>>1;
return x<=tr[k<<1]?query_num(x,ls):query_num(x-tr[k<<1],rs);
}
}
using namespace Segment_Tree;
inline void disc_init(){
sort(b+1,b+b[0]+1);
b[0]=unique(b+1,b+b[0]+1)-b-1;
FOR(i,1,n)
a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
}
int main(){
scanf("%d",&n);
b[++b[0]]=-inf,b[++b[0]]=inf;
FOR(i,1,n)scanf("%d",a+i),b[++b[0]]=a[i];
disc_init();
query_rank(1),query_rank(b[0]);
FOR(i,1,n){
pos=query_rank(a[i]);
ans+=(i==1?b[a[i]]:min(b[a[i]]-b[query_num(pos-1)],b[query_num(pos+1)]-b[a[i]]));
}
printf("%d\n",ans);
return 0;
}