学习splay tree的模版题。
网址:http://www.wikioi.com/problem/1296/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 110000
#define INF 99999999
struct splaytree//封装伸展树
{
//maxn:伸展树的点的个数
int pre[maxn];//前驱
int key[maxn];//键值
int ch[maxn][2];//左右孩子
int root,tot;//根节点,节点数量
void init(){
tot=root=0;
memset(ch,0,sizeof(ch));
memset(pre,0,sizeof(pre));
memset(key,0,sizeof(key));
}
void newnode(int &r,int father,int k){//在r位置,父亲为father,新建一个值为x的新节点。
r=++tot;
pre[r]=father;
key[r]=k;
ch[r][0]=ch[r][1]=0;
}
void rot(int x,int kind){//kind=1,右旋.kind=0,左旋
int y=pre[x];
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
ch[x][kind]=y;
if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
pre[y]=x;
}
void splay(int x,int goal){//把x伸展到目标位置
while(pre[x]!=goal){
if(pre[pre[x]]==goal)rot(x,ch[pre[x]][0]==x);
else{
int y=pre[x];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x){
rot(x,!kind);
rot(x,kind);
}
else{
rot(y,kind);
rot(x,kind);
}
}
}
if(goal==0)root=x;//把root更新成x
}
int insert(int x){//插入值x
int r=root;
while(ch[r][key[r]<x]){
if(key[r]==x){
splay(r,0);
return 0;
}
r=ch[r][key[r]<x];
}
newnode(ch[r][x>key[r]],r,x);
splay(ch[r][x>key[r]],0);
return 1;
}
int get_pre(int x){//寻找节点x的前驱的值,未找到,反回INF
int r=ch[x][0];
if(r==0)return -INF;
while(ch[r][1])r=ch[r][1];
return key[r];
}
int get_next(int x){//寻找节点x的后继的值,未找到,反回INF
int r=ch[x][1];
if(r==0)return INF;
while(ch[r][0])r=ch[r][0];
return key[r];
}
}tree;
int main()
{
int n,i;
while(~scanf("%d",&n))
{
int sum=0;
int x;
tree.init();
for(i=1;i<=n;i++)
{
if(scanf("%d",&x)==EOF)x=0;
if(i==1)
{
sum+=x;
tree.newnode(tree.root,0,x);
continue;
}
if(tree.insert(x)==0)continue;
int a=tree.get_pre(tree.root);
int b=tree.get_next(tree.root);
// cout<<a<<" "<<x<<" "<<b<<endl;
sum+=min(x-a,b-x);
}
printf("%d\n",sum);
}
return 0;
}