代码源堆例题:大富翁

思路:本题简要的来说就是,让你初始化一个每个节点值都为100的堆,并且他们都有自己各自的编号,然后要有两个功能,第一个功能是能直接指明第n个节点,并且要让他变大或者变小(保证最大堆或者最小堆的基本性质),第二个功能就是查询最大堆和最小堆的根节点。

反思:

1.节点在堆中的编号和题目要求的容易混淆,相当于每个不同的人在固定的岗位上轮换工作,这里我定义了两个数组,分别暗藏与大根堆和小根堆中,他们记录每个节点的真实编号和虚假编号,如person[真实编号]=虚假编号,而我定义了结构体数组,每个节点也记录了自己的真实编号(真实编号是index)

2.切记更新编号时不仅要更新节点的编号,也要更新person的。

3.大根堆和小根堆要完完全全分开来做。

#include<iostream>
#include<math.h>
using namespace std;
const int N = 1001;
int len1 = 0, len2 = 0;

struct node1
{
	int val;
	int index;
}head1[N];
struct node2
{
	int val;
	int index;
}head2[N];
int person1[N] = { N };
int person2[N] = { N };
//最小堆
void up_min(int i)
{
	while (i != 1 && head1[i].val < head1[i / 2].val)
	{
		swap(head1[i], head1[i / 2]);
		person1[head1[i].index] = i/2;
		i = i / 2;
	}
}
void down_min(int i)
{
	while (i * 2 <= len1)
	{
		int j = i * 2;
		if (j + 1 <= len1 && head1[j].val > head1[j + 1].val)j = j + 1;
		if (head1[i].val < head1[j].val) break;
		swap(head1[i], head1[j]);
		person1[head1[i].index] = j;
		i = j;
	}
}
//最大堆
void up_max(int i)
{
	while (i != 1 && head2[i].val > head2[i / 2].val)
	{
		swap(head2[i], head2[i / 2]);
		person2[head2[i].index] = i/2;
		i /= 2;
	}
}
void down_max(int i)
{
	while (i * 2 <= len2)
	{
		int j = i * 2;
		if (j + 1 <= len2 && head2[j + 1].val > head2[j].val)j++;
		if (head2[i].val > head2[j].val) break;
		swap(head2[i], head2[j]);
		person2[head2[i].index] = j;
		i = j;
		
	}
}
void min_(int i,int x)
{
	if (x == 0) return;
	if (x < 0)up_min(i);
	if (x > 0)down_min(i);
}
void max_(int i, int x)
{
	if (x == 0) return;
	if (x < 0)down_max(i);
	if (x > 0)up_max(i);
}
int main()
{
	int n;cin >> n;
	while (n--)
	{
		head1[++len1].val = 100;
		head1[len1].index = len1;
		person1[len1] = len1;
		head2[++len2].val = 100;
		head2[len2].index = len2;
		person2[len2] = len2;
	}
	int m;cin >> m;
	while (m--)
	{
		int z=0;
		cin >> z;
		if (z == 1)
		{
			int p, x;cin >> p >> x;
			head1[person1[p]].val += x;
			min_(person1[p], x);
			head2[person2[p]].val += x;
			max_(person2[p], x);
		}
		if (z == 2)
		{
			cout << head2[1].val;
			cout << head1[1].val;
		}
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值