【ybotj 高效进阶 4.1】【二叉堆】龙珠游戏

【ybotj 高效进阶 4.1】【二叉堆】龙珠游戏

题目

在这里插入图片描述
在这里插入图片描述


解题思路

要取相邻的两颗龙珠
那么第一颗不能取最后一颗
所以一开始第n颗不能在二叉堆中排序
next数组标记下一个相邻龙珠的位置
每次取出最大的龙珠 不能是最后一个 以及ta相邻的一个
然后标记被取过,更新next数组


代码

#include<iostream>
#include<cstdio>
using namespace std;
struct lzf{
	int z,w;
}tree[100200];
int n,t,a[100010],b[100010],next[100010];
void put(int x,int y)
{
	 tree[++t].z=x;
	 tree[t].w=y;
	 int son=t;
	 while (son>1)
	 {
	 	   int fa=son/2;
	 	   if (tree[son].z<tree[fa].z)
	 	      return;
	 	   swap(tree[son],tree[fa]);
	 	   son=fa;
	 }
}
void get()
{
	lzf res=tree[1]; 
	tree[1]=tree[t--]; 
	int fa=1;
	while (fa*2<=t)
	{
		  int son=fa*2;
		  if (tree[son].z<tree[son+1].z&&son+1<=t) son++;
		  if (tree[son].z<tree[fa].z) break;
		  swap(tree[son],tree[fa]);
		  fa=son;
	}
	if (b[res.w]==1) return get();  //被取过,再取一次
	while (b[next[res.w]]==1&&next[res.w]<=n)  //如果下一个被取过,继续往后取
	      next[res.w]=next[next[res.w]];
	if (next[res.w]>n) return get();  //第二个没得取,再取一次
	printf("%d %d ",a[res.w],a[next[res.w]]);  
	b[res.w]=b[next[res.w]]=1;  //标记被取过
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		next[i]=i+1;
		if (i!=n) 
		   put(a[i],i);
		   else {
		   	    tree[++t].z=a[i];
	            tree[t].w=i;  //第n颗进入二叉堆,不用维护
		   }
	}
    for (int i=1;i<=n/2;i++) get();
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值