伸展树
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define maxn 110000 #define INF 99999999 struct splaytree { 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=++tot; pre[r]=father; key[r]=k; ch[r][0]=ch[r][1]=0; } void rot(int x,int kind)//zuo haizi you xuan { int y=pre[x];//待伸展点的前驱 ch[y][!kind]=ch[x][kind];//待伸展点与旋转方向相同的子节点赋值给待伸展点父节点的待伸展点方向作为孩子 pre[ch[x][kind]]=y;//原待伸展节点伸展方向的子节点前驱改为待伸展节点的父节点 ch[x][kind]=y;//待伸展点父节点赋值给待伸展点旋转方向作为子节点 //以上3步完成待伸展节点子节点、待伸展节点父节点的移动 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) { 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; //待伸展点前驱的前驱的左孩子是否是待伸展点的前驱,是为1 if(ch[y][kind]==x) { rot(x,!kind); rot(x,kind); } else { rot(y,kind); rot(x,kind); } } } if(goal==0) root=x; } int insert(int x) { int r=root; while(ch[r][key[r]<x])//0 zuo 1 you { if(key[r]==x) { splay(r,0); return 0; } r=ch[r][key[r]<x]; } newnode(ch[r][key[r]<x],r,x); splay(ch[r][key[r]<x],0); return 1; } int get_pre(int x) { 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) { 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; scanf("%d",&n); int sum=0; int x; tree.init(); for(int i=1;i<=n;i++) { scanf("%d",&x); 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); sum+=min(x-a,b-x); } printf("%d\n",sum); }