题目大意:中文
注释代码:
/*
* Problem ID : BZOJ 1588 营业额统计
* Author : Lirx.t.Una
* Language : C++
* Run Time : 112 ms
* Run Memory : 1216 KB
*/
#include <stdio.h>
//树的规模
#define MAXSIZE 35000
//树的数组形式
int lft[MAXSIZE];
int rht[MAXSIZE];
int key[MAXSIZE];
int g;//记录当前树有多少结点
int
splay( int tree, int k ) {
int nt;//即node
int tl, tr;
int tt;//即ttmp
if ( !tree ) return 0;
nt = g;//先利用一个未使用的结点作为嫁接树的树根
tl = g;
tr = g;
lft[nt] = 0;
rht[nt] = 0;
while (1) {
if ( k == key[tree] ) break;
if ( k < key[tree] ) {
if ( !lft[tree] ) break;
if ( k < key[ lft[tree] ] ) {
tt = lft[tree];
lft[tree] = rht[tt];
rht[tt] = tree;
tree = tt;
if ( !lft[tree] ) break;
}
lft[tr] = tree;
tr = tree;
tree = lft[tree];
}
else {
if ( !rht[tree] ) break;
if ( k > key[ rht[tree] ] ) {
tt = rht[tree];
rht[tree] = lft[tt];
lft[tt] = tree;
tree = tt;
if ( !rht[tree] ) break;
}
rht[tl] = tree;
tl = tree;
tree = rht[tree];
}
}
rht[tl] = lft[tree];
lft[tr] = rht[tree];
lft[tree] = rht[nt];
rht[tree] = lft[nt];
return tree;
}
bool
find( int &tree, int k ) {//在树中查找关键字
if ( !tree ) return false;
if ( k == key[ tree = splay( tree, k ) ] ) return true;
return false;
}
int
insert( int tree, int k ) {
lft[g] = 0;
rht[g] = 0;
key[g] = k;
if ( !tree ) return g++;
if ( k < key[tree] ) {
lft[g] = lft[tree];
rht[g] = tree;
lft[tree] = 0;
}
else {
rht[g] = rht[tree];
lft[g] = tree;
rht[tree] = 0;
}
return g++;
}
inline int
min( int a, int b ) {
return a < b ? a : b;
}
int
dis(int tree) {//计算刚插入结点和之前插入的结点关键字的最小差
int l_clo, r_clo;//lft_closest、rht_closest,左右子树中和tree最接近的值
int k;//当前tree值
k = key[tree];
if ( !lft[tree] ) l_clo = -1;
else l_clo = key[ lft[tree] = splay( lft[tree], k ) ];
if ( !rht[tree] ) r_clo = -1;
else r_clo = key[ rht[tree] = splay( rht[tree], k ) ];
if ( -1 == l_clo && -1 == r_clo ) return k;
if ( -1 == l_clo ) return r_clo - k;
if ( -1 == r_clo ) return k - l_clo;
return min( k - l_clo, r_clo - k );
}
int
main() {
int n;//序列长度
int ans;//最终答案
int k;//每次输入的键值
int tree;//splay树
//初始化
tree = 0;
ans = 0;
g = 1;
scanf("%d", &n);
while ( n-- ) {
if ( EOF == scanf("%d", &k) ) k = 0;//非常坑爹的地方
if ( find( tree, k ) ) continue;//如果之前存在则差值一定是0因此没必要插入
tree = insert( tree, k );
ans += dis(tree);
}
printf("%d\n", ans);
return 0;
}
无注释代码:
#include <stdio.h>
#define MAXSIZE 35000
int lft[MAXSIZE];
int rht[MAXSIZE];
int key[MAXSIZE];
int g;
int
splay( int tree, int k ) {
int nt;
int tl, tr;
int tt;
if ( !tree ) return 0;
nt = g;
tl = g;
tr = g;
lft[nt] = 0;
rht[nt] = 0;
while (1) {
if ( k == key[tree] ) break;
if ( k < key[tree] ) {
if ( !lft[tree] ) break;
if ( k < key[ lft[tree] ] ) {
tt = lft[tree];
lft[tree] = rht[tt];
rht[tt] = tree;
tree = tt;
if ( !lft[tree] ) break;
}
lft[tr] = tree;
tr = tree;
tree = lft[tree];
}
else {
if ( !rht[tree] ) break;
if ( k > key[ rht[tree] ] ) {
tt = rht[tree];
rht[tree] = lft[tt];
lft[tt] = tree;
tree = tt;
if ( !rht[tree] ) break;
}
rht[tl] = tree;
tl = tree;
tree = rht[tree];
}
}
rht[tl] = lft[tree];
lft[tr] = rht[tree];
lft[tree] = rht[nt];
rht[tree] = lft[nt];
return tree;
}
bool
find( int &tree, int k ) {
if ( !tree ) return false;
if ( k == key[ tree = splay( tree, k ) ] ) return true;
return false;
}
int
insert( int tree, int k ) {
lft[g] = 0;
rht[g] = 0;
key[g] = k;
if ( !tree ) return g++;
if ( k < key[tree] ) {
lft[g] = lft[tree];
rht[g] = tree;
lft[tree] = 0;
}
else {
rht[g] = rht[tree];
lft[g] = tree;
rht[tree] = 0;
}
return g++;
}
inline int
min( int a, int b ) {
return a < b ? a : b;
}
int
dis(int tree) {
int l_clo, r_clo;
int k;
k = key[tree];
if ( !lft[tree] ) l_clo = -1;
else l_clo = key[ lft[tree] = splay( lft[tree], k ) ];
if ( !rht[tree] ) r_clo = -1;
else r_clo = key[ rht[tree] = splay( rht[tree], k ) ];
if ( -1 == l_clo && -1 == r_clo ) return k;
if ( -1 == l_clo ) return r_clo - k;
if ( -1 == r_clo ) return k - l_clo;
return min( k - l_clo, r_clo - k );
}
int
main() {
int n;
int ans;
int k;
int tree;
tree = 0;
ans = 0;
g = 1;
scanf("%d", &n);
while ( n-- ) {
if ( EOF == scanf("%d", &k) ) k = 0;
if ( find( tree, k ) ) continue;
tree = insert( tree, k );
ans += dis(tree);
}
printf("%d\n", ans);
return 0;
}