洛谷原题:
点击打开链接
splay的模板?是的吧=_=
又臭又长的splay完美的契合了这个题~~~~
题意:
对于每一个数据,找到出现在其前面的一个与他最接近的数据。做差,并将所有差求和输出。
做法:
逐个将每个数插入splay树中:
1、寻找每个点的前驱、后继。
2、将当前数据分别与找到的前驱、后继做差,取小。
3、将每次取到的差求和。
贴代码(最最基本的splay写法):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
//splay
const int NUM=32800;
int tot,root,ans,a,b,c,n;//总数,树根的节点号
struct Treetype
{
int val;
int father,lch,rch; //父亲,左孩子,右孩子
int num; //该点相同值的个数
int ln,rn; //左右子树结点的个数
}tree[NUM];
void preorder(int pos)//pos是当前的点的编号。
{
if(tree[pos].val)printf("%d ",tree[pos].val);
if(tree[pos].lch)preorder(tree[pos].lch);
if(tree[pos].rch)preorder(tree[pos].rch);
}
void inorder(int pos)
{
if(tree[pos].lch)inorder(tree[pos].lch);
if(tree[pos].val)printf("%d ",tree[pos].val);
if(tree[pos].rch)inorder(tree[pos].rch);
}
//左旋
void zag(int x)
{
int y=tree[x].father;
tree[y].rch=tree[x].lch;
if(tree[x].lch)tree[tree[x].lch].father=y;
tree[x].father=tree[y].father;
if(tree[y].father)
{
if(tree[tree[y].father].lch==y)
tree[tree[y].father].lch=x;
else
tree[tree[y].father].rch=x;
}
tree[x].lch=y;
tree[y].father=x;
tree[y].rn=tree[x].ln;
tree[x].ln=tree[y].rn+tree[y].ln+1;
}
//右旋
void zig(int x)
{
int y=tree[x].father;
tree[y].lch=tree[x].rch;
if(tree[x].rch)tree[tree[x].rch].father=y;
tree[x].father=tree[y].father;
if(tree[y].father)
{
if(tree[tree[y].father].lch==y)
tree[tree[y].father].lch=x;
else
tree[tree[y].father].rch=x;
}
tree[x].rch=y;
tree[y].father=x;
tree[y].ln=tree[x].rn;
tree[x].rn=tree[y].rn+tree[y].ln+1;
}
//伸展操作
void splay(int x)
{
int p;
while (tree[x].father)
{
p=tree[x].father;
if(!tree[p].father)
{
if(x==tree[p].lch)zig(x);
else zag(x);
break;
}
if(x==tree[p].lch)
{
if(tree[tree[p].father].lch==p){zig(p);zig(x);}
else {zig(x);zag(x);}
}
if(x==tree[p].rch)
{
if(tree[tree[p].father].rch==p){zag(p);zag(x);}
else {zag(x);zig(x);}
}
}
root=x;
}
//查找
int find(int x)
{
int p=root;
while(p)
{
if(x==tree[p].val){splay(p);return 1;}
if(x<tree[p].val)p=tree[p].lch;
else p=tree[p].rch;
}
return 0;
}
//插入
void insert (int x)
{
int p,f;
p=root;
while(p)
{
f=p;
if(x<=tree[p].val){tree[p].ln++;p=tree[p].lch;}
else{tree[p].rn++;p=tree[p].rch;}
}
tot++;
tree[tot].val=x;
tree[tot].father=0;
tree[tot].lch=0;
tree[tot].rch=0;
tree[tot].ln=0;
tree[tot].rn=0;
if(root==0)
{
root=tot;
return;
}
tree[tot].father=f;
if(x<=tree[f].val)tree[f].lch=tot;
else tree[f].rch=tot;
splay(tot);
}
//求前驱
int pred(int x)
{
find(x);
int p=tree[root].lch;
while(p){if(tree[p].rch==0)break;p=tree[p].rch;}
if(p)return tree[p].val;
return 0x7fffffff;
}
//求后继
int succ(int x)
{
find(x);
int p=tree[root].rch;
while(p){if(tree[p].lch==0)break;p=tree[p].lch;}
if(p)return tree[p].val;
return 0x7fffffff;
}
int main()
{
// freopen("turnover.in","r",stdin);
// freopen("turnover.out","w",stdout);
// freopen("P2234.txt","r",stdin);
scanf("%d",&n);
scanf("%d",&a);
insert(a);
ans=a;
for(int i=1;i<=n-1;i++)
{
scanf("%d",&a);
insert(a);
b=pred(a)-a;
c=succ(a)-a;
ans+=min(abs(c),abs(b));
}
printf("%d\n",ans);
}