题目描述
题解
平衡树练习。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int max_n=40005;
const int INF=2e9;
int n,x;
int f[max_n],ch[max_n][2],key[max_n],cnt[max_n];
int root,sz,last;
int ans;
inline int Abs(int a,int b){
if (a>b) return a-b;
else return b-a;
}
inline int get(int x){
return ch[ f[x] ][1]==x;
}
inline void rotate(int x){
int old=f[x],oldf=f[old],which=get(x);
ch[old][which]=ch[x][which^1];
f[ ch[old][which] ]=old;
ch[x][which^1]=old;
f[old]=x;
f[x]=oldf;
if (oldf)
ch[oldf][ ch[oldf][1]==old ]=x;
}
inline void splay(int x){
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate( (get(x)==get(fa)) ?fa:x);
root=x;
}
inline void Insert(int x){
if (root==0){
root=++sz;
f[sz]=ch[sz][0]=ch[sz][1]=0;
cnt[sz]=1;
key[sz]=x;
return;
}
int now=root,fa=0;
while (1){
if (x==key[now]){
cnt[now]++;
splay(now);
break;
}
fa=now;
now=ch[now][ key[now]<x ];
if (now==0){
sz++;
f[sz]=fa;
ch[sz][0]=ch[sz][1]=0;
cnt[sz]=1;
key[sz]=x;
ch[fa][ key[fa]<x ]=sz;
splay(sz);
break;
}
}
}
inline int Find_Pre(int x){
if (cnt[root]>1)
return x;
if (!ch[root][0]) return -INF;
int now=ch[root][0];
while (ch[now][1])
now=ch[now][1];
return key[now];
}
inline int Find_Next(int x){
if (cnt[root]>1)
return x;
if (!ch[root][1]) return -INF;
int now=ch[root][1];
while (ch[now][0])
now=ch[now][0];
return key[now];
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i){
if (scanf("%d",&x)==EOF) x=0;
Insert(x);
int pre=Find_Pre(x);
int next=Find_Next(x);
if (i==1){
ans+=x;
continue;
}
ans+=min( Abs(x,pre) , Abs(x,next) );
}
printf("%d\n",ans);
}
总结
错误记录:
没有前驱或者没有后继的情况,考虑了,但是不够全面。