splay学习第一题。代码基本看cxlove的。splay操作根据看到的伪代码简化了下。原来的代码也附上。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 100005
#define mod 20140518
#define inf 1 << 29;
typedef long long LL;
int pre[N], key[N], ch[N][2], root, tot1;
//ch[][0]为左孩子,ch[][1]为右孩子
int n;
void NewNode(int &r, int father, int k){
r = ++tot1;
pre[r] = father;
key[r] = k;
ch[r][0] = ch[r][1] = 0;
}
//kind = 1为右旋,kind为0左旋
void Rotate(int x,int kind){
int y = pre[x];
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y]){
ch[pre[y]][ch[pre[y]][1] == y] = x;
}//y节点有父节点用x节点将其替代
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
}
//将根为r的子树调整为goal
/*void Splay(int r, int goal){
while(pre[r] != goal){
if(pre[pre[r]] == goal)
Rotate(r, ch[pre[r]][0] == r);
else{
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r){
Rotate(r, !kind);
Rotate(r, kind);
}
else {
Rotate(y, kind);
Rotate(r, kind);
}
}
}
if(goal == 0)root = r;
}*/
void Splay(int r, int goal){
while(pre[r] != goal){
int y = pre[r];
int kind = (ch[y][0] == r);
if(pre[y] != goal && (kind == (ch[pre[y]][0] == y))){
Rotate(y, kind);
}
Rotate(r, kind);
}
if(goal == 0)root = r;
}
int Insert(int k){
int r = root;
while(ch[r][key[r] < k]){
//不重复插入
if(key[r] == k){
Splay(r, 0);
return 0;
}
r = ch[r][key[r] < k];
}
NewNode(ch[r][k > key[r]], r, k);
Splay(ch[r][k > key[r]], 0);
return 1;
}
//前驱
int get_pre(int x){
int tmp = ch[x][0];
if(tmp == 0) return inf;
while(ch[tmp][1])
tmp = ch[tmp][1];
return key[x] - key[tmp];
}
//后继
int get_next(int x){
int tmp = ch[x][1];
if(tmp == 0)return inf;
while(ch[tmp][0])
tmp = ch[tmp][0];
return key[tmp] - key[x];
}
int main(){
while(scanf("%d", &n) != EOF){
root = tot1 = 0;
int ans = 0;
for(int i = 1; i <= n; i++){
int num;
if(scanf("%d", &num) == EOF) num = 0;
if(i == 1){
ans += num;
NewNode(root, 0, num);
continue;
}
if(Insert(num) == 0)continue;
int a = get_next(root);
int b = get_pre(root);
ans += min(a, b);
}
printf("%d\n", ans);
}
return 0;
}