BZOJ 1588 营业额统计

题目大意:中文

题目链接

注释代码:

/*
 * 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值