【平衡二叉树】超市促销

题目:超市促销

题目描述

球球和小姜管理着巨大的校园超市联盟,听说今年将有很多OIer到学校来参加NOIP,他俩决定在NOIP期间(包括准备期间)举行促销活动。
促销活动必须遵守下列规定:
想要参加促销的每位OIer,必须将自己的每笔消费账单丟入指定的盒子里。每天活动结束时,球球和小姜会从盒子里挑出金额最大和最小的两张账单。消费最多的客户将要得到一笔奖金! 数额是挑出的两张金额的差的绝对值。输入数据保证每天总可以找到两张账单。
为了避免重复获奖,每天挑出的账单不能重新放回盒子里,其余的账单将留在盒中,继续参加促销活动,直到活动结束。
在紧张的复习NOIP阶段,球球和小姜实在没有精力来计算促销活动的花费,他们找到了聪明的你,你的任务是根据每天活动的信息算出促销活动的总花费。

输入格式

输入的第一行是一个整数n,表示促销的天数。(1 <= n <= 5000)
在接下来的n行中,每行有若干个非负整数,用空格隔开。第i+1行的数据代表第i天的账单信息,每行第一个整数k(0 <= k <= 10^5)。表示今天有多少个新账单。接下来k个正整数表示每张账单的金额wij(1 <= wij <= 10^6)

输出格式

输出中只有一个整数,表示整个促销活动期间所有的花费。

样例输入

样例输出


#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <cstdio>

const long maxn = 5010;
long n;long root = 0;
long rs[maxn];
long ls[maxn];
long tree[maxn];
long sum[maxn];
long hr[maxn];
long top = 0;

long ABS(long a)
{
	return a>0?a:-a;
}

void l_rotate(long &k)
{
	long tmp = rs[k];
	rs[k] = ls[tmp];
	ls[tmp] = k;
	
	sum[tmp] = sum[k];
	sum[k] = sum[ls[k]]+sum[rs[k]];
	k = tmp;
}

void r_rotate(long &k)
{
	long tmp = ls[k];
	ls[k] = rs[tmp];
	rs[tmp] = k;
	
	sum[tmp] = sum[k];
	sum[k] = sum[ls[k]]+sum[rs[k]];
	k = tmp;
}

void insert(long& k,long v)
{
	if (k == 0)
	{
		top ++;
		tree[top] = v;
		hr[top] = rand();
		sum[v] = 1;
		k = top;
		return;	
	}
	sum[k] ++;
	if (v <= tree[k])
	{
		insert(ls[k],v);
		if (hr[ls[k]]<hr[k])
			r_rotate(k);
	}
	else
	{
		insert(rs[k],v);
		if (hr[rs[k]]<hr[k])
			l_rotate(k);
	}
}

long first(long &k)
{
	if (!ls[k]){long tmp=k;k=rs[k];return tree[tmp];}
	return first(ls[k]);
}

long last(long &k)
{
	if (!rs[k]){long tmp=k;k=ls[k];return tree[tmp];}
	return last(rs[k]);	
}

inline int getint()
{
	int rs=0;char tmp;bool sgn=1;
	do tmp = getchar();
	while (!(isdigit(tmp))&&tmp-'-');
	if (tmp=='-'){tmp=getchar();sgn=0;}
	do rs = (rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;
}

int main()
{
	n = getint();
	long ans = 0;
	for (long i=1;i<n+1;i++)
	{
		long k = getint();
		while ( k -- )
			insert(root,getint());
		ans += ABS(first(root)-last(root));
	}
	if (ans-2)
		printf("%ld",ans);
	else
		printf(" ");
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值