大水题啊
很多种方法
对于开始学splay的我
就当一个练手题了。。。
特别吐槽
bzoj数据不对
有些数据说好的n行
却读入不够n行
加上
if(scanf("%d",&t) == EOF) t = 0;
才能A
草
害我白错几次
幸好用小号、。。。。
#include <cstdio>
#include <iostream>
#define D 100000
#define lp(i,j,k) for(int i = j;i <= k;++i)
using namespace std;
int abs (int X) {
if(X > 0)
return X;
return -X;
}
int n,t,a;
int ch[D][2],root = 1,x[D],fa[D],cnt,tim[D];
int point (int X,int now) {
int d;
if(x[now] > X)
d = 0;
else {
if(x[now] < X) {
d = 1;
}
else return -1;
}
return d;
}
void rot (int now,int d) {
int temp = fa[now];
ch[ fa[now] ][d ^ 1] = ch[now][d];
fa[ch[now][d]] = fa[now];
ch[now][d] = fa[now];
fa[now] = fa[fa[now]];
fa[temp] = now;
if(!fa[now])
return;
if(ch[fa[now]][1] == temp)
ch[fa[now]][1] = now;
else ch[fa[now]][0] = now;
}
void splay (int X,int &goal) {
if(X == goal)
return;
while(fa[X] != 0) {
if(fa[fa[X]]) {
int T = 0;
lp(i,0,1) {
lp(j,0,1) {
if(ch[ fa[fa[X]] ][i] == fa[X] && ch[ fa[X] ][j] == X ) {
rot(X,j ^ 1);
rot(X,i ^ 1);
T = 1;
break;
}
}
if(T) break;
}
}
else rot(X, ch[goal][1] == X ? 0 : 1 );
}
goal = X;
}
void insert (int X,int now) {
if(cnt == 0) {
x[now] = X;
++cnt;
++tim[now];
return;
}
int d = point(X,now);
if(d == -1) {
++tim[now];
splay(now,root);
return;
}
if(!ch[now][d]) {
ch[now][d] = ++cnt;
fa[cnt] = now;
x[cnt] = X;
++tim[cnt];
splay(cnt,root);
return;
}
else insert(X,ch[now][d]);
}
int search (int d) { //前驱 1 后继 0
if(tim[root] >= 2)
return x[root];
int p = ch[root][d ^ 1];
if(!p)
return 0x3f3f3f3f;
while(ch[p][d])
p = ch[p][d];
return x[p];
}
void solve () {
lp(i,1,n) {
if(scanf("%d",&t) == EOF) t = 0;
insert(t,root);
if(i == 1) {
a += x[root];
continue;
}
int t1 = abs(search(1) - t);
int t2 = abs(search(0) - t);
a += min(t1,t2);
}
printf("%d\n",a);
}
int main () {
scanf("%d",&n);
solve();
}