题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588
#include<stdio.h> #include<string.h> const int N=100100; const int inf=0x3fffffff; #define min(a,b) (a>b?b:a) int root,tot; struct Tree { int key,son[2],father; }T[N];//son[0]左儿子,son[1]右儿子 void newnode(int &r,int w,int fa)//建新节点 { r=++tot; T[r].key=w;T[r].father=fa; T[r].son[0]=T[r].son[1]=0; } void Rotate(int r,int kind)//旋转,kind为1是右旋,为0是左旋 { int y=T[r].father; T[y].son[!kind]=T[r].son[kind]; T[T[r].son[kind]].father=y; if(T[y].father) T[T[y].father].son[T[T[y].father].son[1]==y]=r; T[r].father=T[y].father; T[r].son[kind]=y; T[y].father=r; } //Splay调整,将结点r调整到goal下面(以r为根节点) void Splay(int r,int goal) { int y; while(T[r].father!=goal) { y=T[r].father; if(T[y].father==goal) Rotate(r,T[y].son[0]==r); else { int kind=T[T[y].father].son[0]==y; if(T[y].son[kind]==r) { Rotate(r,!kind); Rotate(r,kind); } else { Rotate(y,kind); Rotate(r,kind); } } } if(goal==0)root=r;//更新根节点 } bool insert(int w) { int r=root; while(T[r].son[w>T[r].key]) { if(T[r].key==w)//如果w已经在树中 { Splay(r,0); return false; } r=T[r].son[w>T[r].key]; } newnode(T[r].son[w>T[r].key],w,r); Splay(T[r].son[w>T[r].key],0); return true; } int get_pre(int r)//在左子树中找到最大的值(找前驱) { int temp=T[r].son[0]; if(temp==0)return inf; while(T[temp].son[1]) temp=T[temp].son[1]; return T[r].key-T[temp].key; } int get_next(int r)//在右子树中找到最小的值(找后继) { int temp=T[r].son[1]; if(temp==0)return inf; while(T[temp].son[0]) temp=T[temp].son[0]; return T[temp].key-T[r].key; } int main() { int n,w,sum,j; while(scanf("%d",&n)!=-1) { sum=0;root=tot=0; if(scanf("%d",&w)==EOF)w=0; sum+=w; newnode(root,w,0); for(j=1;j<n;j++) { if(scanf("%d",&w)==EOF)w=0; if(!insert(w))continue; sum+=min(get_pre(root),get_next(root)); } printf("%d\n",sum); } return 0; }