最近开始重新学习Splay树写的第一题,基本就是照着别人博客改的一道题,关于Splay树的模板,感觉大牛已经把代码改得很短!!!这道题没什么难度,一个插入操作,一个找前驱,一个找后驱的操作。(话说这题有个数据有个bug的地方,可以看连接的discuss)。因为没有Push_Down,Push_Up的操作,感觉这题应该算是Splay树里面最水的一道了吧。
下面附上代码:(因为是第一题写Splay树,照着别人模板写的,然后写后面题的时候逐渐完善了一下)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
#define MAXN 110000
using namespace std;
struct SplayTree{
int root,size;
int nt[MAXN][2],pre[MAXN],val[MAXN];
void init() {root = size = 0;}
void newnode(int& rt,int father,int value){
rt = ++size;
nt[rt][0] = nt[rt][1] = 0;
pre[rt] = father;
val[rt] = value;
}
void rotate(int x,int kind){ //0代表左旋,1代表右旋
int y = pre[x];
nt[y][!kind] = nt[x][kind];
pre[nt[x][kind]] = y;
if(pre[y]){
nt[pre[y]][nt[pre[y]][1] == y] = x;
}
pre[x] = pre[y];
nt[x][kind] = y;
pre[y] = x;
}
void Splay(int x,int goal){
while (pre[x] != goal) {
if(pre[pre[x]] == goal){
rotate(x,nt[pre[x]][0] == x);
}
else{
int y = pre[x];
int kind = nt[pre[y]][0] == y;
if(nt[y][kind] == x){
rotate(x,!kind);
rotate(x,kind);
}
else{
rotate(y,kind);
rotate(x,kind);
}
}
}
if (!goal)
root = x;
}
bool insert(int k){
int rt = root;
while(nt[rt][val[rt] < k]){
if(val[rt] == k){
Splay(rt,0);
return false;
}
rt = nt[rt][val[rt] < k];
}
newnode(nt[rt][val[rt] < k],rt,k);
Splay(nt[rt][val[rt] < k],0);
return true;
}
int get_pre(){
int x = nt[root][0];
while(x){
while(nt[x][1]){
x = nt[x][1];
}
return val[x];
}
return -1;
}
int get_next(){
int x = nt[root][1];
while(x){
while(nt[x][0]){
x = nt[x][0];
}
return val[x];
}
return -1;
}
};
SplayTree tree;
int main(){
//freopen("test.in","r",stdin);
int n;
while(~scanf("%d",&n)){
int ans,x;
scanf("%d",&ans);
n --;
tree.init();
tree.newnode(tree.root,0,ans);
while(n --){
x = 0;
scanf("%d",&x);
if(tree.insert(x)){
int t1 = tree.get_pre();
int t2 = tree.get_next();
if(t1 == -1) ans += abs(t2 - x);
else if(t2 == -1) ans += abs(x - t1);
else {
ans += min(x - t1,t2 - x);
}
}
}
printf("%d\n",ans);
}
return 0;
}