将每一个依次插入,与前驱和后继进行比较,选取差值小的。如果遇到相同的数已经在树中,则不插入。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100010
#define inf 0x3f3f3f3f
int pre[maxn],key[maxn],ch[maxn][2],root,tot1;
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];
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
//如果父节点不是根节点,则要和父节点的父节点连接起来
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
}
//Splay调整,将根为r的子树调整为goal
void Splay(int r,int goal)
{
while(pre[r] != goal)
{
//父节点即是目标位置,goal为0表示,父节点就是根节点
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;
}
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[tmp] - key[x];
}
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_next(root);
ans += min(a,b);
}
printf("%d\n",ans);
}
return 0;
}
风格更新后:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 100010
#define LL long long int
#define Key_value ch[ch[root][1]][0]
inline int min(int a,int b)
{
return a>b?b:a;
}
struct SplayTree
{
int pre[maxn],key[maxn],ch[maxn][2],root,cnt;
void init()
{
root = cnt = 0;
}
void NewNode(int & r,int father,int k)
{
r = ++cnt;
pre[r] = father;
ch[r][0] = ch[r][1] = 0;
key[r] = k;
}
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 r)
{
int tmp = ch[r][0];
if(tmp == 0) return inf;
while(ch[tmp][1])
tmp = ch[tmp][1];
return key[r] - key[tmp];
}
int Get_Next(int r)
{
int tmp = ch[r][1];
if(tmp == 0) return inf;
while(ch[tmp][0])
tmp = ch[tmp][0];
return key[tmp] - key[r];
}
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;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
}
void Splay(int r,int goal)
{
while(pre[r] != goal)
{
int y = pre[r],z = pre[y];
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);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
if(goal == 0) root = r;
}
void solve(int n)
{
init();
int num,ans = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d",&num);
if(i == 1)
{
NewNode(root,0,num);
ans += num;
}
else
{
if(Insert(num)==0) continue;
int a = Get_Next(root);
int b = Get_Pre(root);
ans += min(a,b);
}
}
printf("%d\n",ans);
}
}spt;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
spt.solve(n);
}
return 0;
}