BZOJ-1588 营业额统计 Treap裸题

大家都很强, 可与之共勉。

二叉排序树(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 ( "" );
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值