大家都很强, 可与之共勉。
二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树。
但是操作里面涉及插入或删除,经过多次之后不见得还能保证二叉搜索树的性质,每次查询不见得还是logn的,我们需要一种操作(几乎成为平衡树的代表标志):旋转(rotate)
还有一种判断是么时候应该旋转的maintain函数。
我们大体上以maintain的不同区分平衡树
treap中如果通过多次插入删除导致数不再平衡了的话,用旋转的方式重新维护平衡树的性质。
左旋:即上图中用x及其子树区替代y的位置,因为x的所有子树的值都是小于y的,而x的右子树的值都是大于x且小于y的,正好在旋转后处于y的左子树,同时我们把y的父节点接到x上,使x成为新的y。
右旋类比左旋
具体看代码
在这里我只想说
我T了那么多次是因为
宏定义min, max有毒
看来是函数传参和#define各有优劣
/**************************************************************
Problem: 1588
User: Lazer2001
Language: C++
Result: Accepted
Time:164 ms
Memory:1608 kb
****************************************************************/
#include <ctime>
#include <cctype>
#include <cstdio>
/*#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))*/
template < class T > inline T max ( T a, T b ) { return (a) > (b) ? (a) : (b); }
template < class T > inline T min ( T a, T b ) { return (a) < (b) ? (a) : (b); }
template < class T >
inline short readIn ( T& x ) {
static char ch;
static short opt;
opt = (ch != 45);
while ( !isdigit ( ch = getchar () ) && (ch ^ -1) && ( ch ^ 45 ) );
if ( ch == -1 ) return 0;
if ( ch == 45 ) { opt = 0; ch = getchar (); }
for ( x = -48 + ch; isdigit ( ch = getchar () ); ( x *= 10 ) += ch - 48 );
opt ? 1 : x = -x;
return 1;
}
template < class T >
inline void writeIn ( T x ) {
static unsigned int top, t[25];
if ( !x ) { putchar ( 48 ); return; }
if ( x < 0 ) { x = -x; putchar ( 45 ); }
while ( x ) t[ ++top ] = x % 10, x /= 10;
while ( top ) putchar ( t[top--] + 48 );
}
inline int rand ( ) {
static int seed = 233;
return seed = ( int ) seed * 482711LL % 2147483647;
}
int n, x, ans, pre, post;
typedef class TreapNode {
public:
int val, key;
TreapNode *ls, *rs;
TreapNode ( ) { }
TreapNode ( int val ) : val ( val ), key ( rand ( ) ) { ls = rs = 0; }
} Treap;
Treap pool[50005], *root, * tail, *tmp;
inline void Zig ( Treap* &nd ) {
tmp = nd -> ls;
nd -> ls = tmp -> rs;
tmp -> rs = nd;
nd = tmp;
}
inline void Zag ( Treap* &nd ) {
tmp = nd -> rs;
nd -> rs = tmp -> ls;
tmp -> ls = nd;
nd = tmp;
}
inline void Insert ( Treap* &nd, int val ) {
if ( !nd ) {
nd = ++tail;
*nd = Treap ( val );
return;
}
if ( nd -> val ^ val ) {
if ( val > nd -> val ) {
Insert ( nd -> rs, val );
if ( nd -> rs -> key > nd -> key )
Zag ( nd );
} else {
Insert ( nd -> ls, val );
if ( nd -> ls -> key > nd -> key )
Zig ( nd );
}
}
}
inline int query_pre ( Treap* &nd, int val ) {
if ( !nd ) return 0xefefefef;
if ( val < nd -> val )
return query_pre ( nd -> ls, val );
return max ( nd -> val, query_pre ( nd -> rs, val ) );
}
inline int query_post ( Treap* &nd, int val ) {
if ( !nd ) return 0x7fffffff;
if ( val > nd -> val )
return query_post ( nd -> rs, val );
return min ( nd -> val, query_post ( nd -> ls, val ) );
}
int main ( ) {
register int i;
while ( readIn ( n ) ) {
root = 0;
tail = pool;
readIn ( x );
Insert ( root, x );
ans = x;
i = 2;
h:;
readIn ( x );
pre = query_pre ( root, x );
post = query_post ( root, x );
ans += min ( x - pre, post - x );
Insert ( root, x );
if ( ++i <= n ) goto h;
writeIn ( ans );
puts ( "" );
}
}