[HNOI2002]营业额统计 Splay tree入门题
题目连接: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;}