http://61.187.179.132/JudgeOnline/problem.php?id=1588
splay,一种功能超级强大的数据结构,且较易实现,核心操作是旋转
求前驱后继
#include <iostream> #include <cstdio> using namespace std ; const int maxn=100005 ; const int INF=0xfffffff ; int son[maxn][2],fa[maxn],key[maxn] ; int rt,size ; void link(int x,int y,int k)//将x连到y的k儿子上 0左1右 { fa[x]=y ; son[y][k]=x ; } void rotate(int x,int k)//k=0 x是y的lson 单旋转 { int y=fa[x] ; link(x,fa[y],son[fa[y]][1]==y) ; link(son[x][!k],y,k) ; link(y,x,!k) ; } void splay(int x,int g) { while(fa[x]!=g) { int y=fa[x],sx=(son[y][1]==x),sy=(son[fa[y]][1]==y) ; if(fa[y]==g) rotate(x,sx) ; else { if(sx==sy) //zig-zig || zag-zag rotate(y,sx) ; else //zig-zag || zag-zig rotate(x,sx) ; rotate(x,sy) ; } } if(!g)rt=x ; } void newnode(int y,int &x,int a) { x=++size ; fa[x]=y ;key[x]=a ; son[x][0]=son[x][1]=0 ; } void insert(int a) { int x=rt ; while(son[x][key[x]<a]) x=son[x][key[x]<a] ; newnode(x,son[x][key[x]<a],a) ; splay(size,0) ; } int pre(int a)//前驱 <=a的最大数 { int x=rt,ans=-INF ; while(x) { if(key[x]==a) return a ; if(key[x]<a) ans=max(ans,key[x]) ; x=son[x][key[x]<a] ; } return ans ; } int suc(int a)//后继 >=a的最小数 { int x=rt,ans=INF ; while(x) { if(key[x]==a) return a ; if(key[x]>a) ans=min(ans,key[x]) ; x=son[x][key[x]<a] ; } return ans ; } int n,a,ans ; int main() { scanf("%d%d",&n,&a) ; ans=a ; insert(a) ; while(--n) { if(scanf("%d",&a)==EOF) a=0 ; ans+=min(a-pre(a),suc(a)-a) ; insert(a) ; } printf("%d\n",ans) ; return 0 ; }