SJTU堆果子的优先级队列优化

堆果子的优先级队列优化

【问题描述】

现在有N堆果子,要把他们合并为一堆。每次合并只能合并其中的两堆,假如要合并的两堆果子分别有a颗果子和b颗果子,那么合并这两堆果子需要消耗a+b点体力。问合并完所有果子需要最小的体力数是多少。
【输入形式】

共两行。

第一行为一个正整数N<=500000。表示果子总共有多少堆。

第二行共N个正整数,ai表示第i堆果子的数目。
【输出形式】

一个正整数,表示消耗的最小体力数。
【样例输入】

5
1 2 3 4 5

【样例输出】

33

【样例说明】

合并1,2消耗体力3,产生一个大小为3的果子堆。

合并4,5消耗体力9,产生一个大小为9的果子堆。

合并3,3消耗体力6,产生一个大小为6的果子堆。

合并6,9消耗体力15,产生一个大小为15的果子堆。

共消耗体力33.

#pragma once
template<class T>
class priorityQueue//class 是类的标志勿忘
{
private:
	int currentLength;
	int maxSize;
	T*array;
	void doubleSpace();
	void percolateDown(int hole);//向下过滤
public:
	void buildHeap();//建堆
	priorityQueue(const T*items, int size);
	priorityQueue(int size = 100)
	{
		maxSize = size;
		currentLength = 0;
		array = new T[size];
	}
	~priorityQueue() { delete[]array; }//构造析构类
	bool isEmpty()const { return currentLength == 0; }//询问类
	T getHead() { return array[1]; }
	void enQueue(const T&x);//非常量引用的初始值必须为左值
	T deQueue();//一般出队都会返回出队值以保存
	int size() { return currentLength; }
};

template < class T>
void priorityQueue<T>::enQueue(const T& x)
{
	if (currentLength == maxSize - 1) doubleSpace();
	int hole = ++currentLength;
	for (; hole > 1 && x < array[hole / 2]; hole /= 2)
		array[hole] = array[hole / 2];
	array[hole] = x;
}
template<class T>
T priorityQueue<T>::deQueue()
{
	T tmp = array[1];
	array[1] = array[currentLength--];//提上来开始落,cl从1开始
	percolateDown(1);//模块化
	return tmp;
}

template<class T>
void priorityQueue<T>::percolateDown(int hole) {
	int child;
	T tmp = array[hole];
	for (; hole * 2 <= currentLength; hole = child)
	{
		child = hole * 2;
		if (child != currentLength && array[child + 1] < array[child])
			child++;
		if (array[child] < tmp) {
			array[hole] = array[child];
		}
		else break;
	}
	array[hole] = tmp;
}

template<class T>
void priorityQueue<T>::doubleSpace()
{
	int i;//留个tmp保存原数据,array扩大
	T*tmp = array;
	array = new T[2 * maxSize];
	for (i = 0; i < maxSize; i++)
	{
		array[i] = tmp[i];
	}
	maxSize *= 2;//成员函数操作对其他变量的影响
	delete tmp;//工具人就是用来delete掉的
}

template<class T>
void priorityQueue<T>::buildHeap()//建堆
{
	int i;
	for (i = currentLength / 2; i >= 1; i--)
	{
		percolateDown(i);//前提是已经构造好
	}
}

template<class T>//带参数的构造函数
priorityQueue<T>::priorityQueue(const T*items, int size)
{

	maxSize = size + 10;
	currentLength = size;
	int i;
	array = new T[maxSize];//此时只是定义了array,尚未赋值,是maxSize
	for (i = 1; i <= currentLength; i++)
	{
		array[i] = items[i - 1];
	}
	buildHeap();
}
#include<iostream>
using namespace std;
int main()
{
	int n, i, tmp1, tmp2;
	long long int sum=0;
	cin >> n;
	priorityQueue<int>x;
	int*t = new int[n];
	for (i = 0; i <= n - 1; i++)
	{
		cin >> t[i];
		x.enQueue(t[i]);
	}
	while (x.size()>1)
	{
		tmp1 = x.deQueue();
		tmp2 = x.deQueue();
		x.enQueue(tmp1 + tmp2);
		sum = sum + tmp1 + tmp2;
	}
	cout << sum << '\n';
	system("pause");
	delete[]t;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值