luogu1090:合并果子:过程排序+求最小值

题目连接:该题是luogu试炼场的2-6:T1


题目大意:

1 给n个数字的序列,(每次取最小的两个相加,得到新的数字),这个数字再放回原序列,直到序列里只有一个数;
2 求:过程中产生的和的总量;
3 例如:
                原序列为:1 2 3 5;
1+2=3:  新序列为:3 3 5;
3+3=6:  新序列为:5 6;
5+6=11:新序列为:11.
所以答案是:3+6+11=20.


解题思路:
1 因为数字是可以随意调换顺序的,所以每次都是要找最小值出来,因此想到了堆;
2 用一个堆来维护这些数字,每次取最小值,然后把加好的新值放回堆中;
3 直到堆里值剩下一个元素,记录过程的和就好了。


上代码:
 

//luogu1181:数列分段 

//解题思路:
//1 一用一个堆维护最小值 
//2 每次取最小的两个值相加
//3 直到全部合并
 
#include
#include

int n;
int a[10010];

void sdown(int x)//向下的维护堆 
{
	int f,s,t=x;
	f=x; s=f*2;
	if(s<=n && a[f]>a[s]) t=s; //问 左儿子 
	if(s+1<=n && a[t]>a[s+1]) t=s+1;//问 右儿子 
	
	if(t!=x) //要交换 
	{
		int k=a[f]; a[f]=a[t]; a[t]=k;
		sdown(t);
	} 
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	
	for(int i=n/2;i>=1;i--) //建堆 
	{
		sdown(i);
	}
	
	int ans=0,k;
	
	while(n>1)//堆还有多个元素 
	{
		k=0;
		ans+=a[1]; k+=a[1]; //拿第一个数 
		
		a[1]=a[n]; n--; sdown(1); //维护
		 
		ans+=a[1]; k+=a[1]; //拿第二个数
		
		a[1]=k; sdown(1); //维护
	}
	
	printf("%d",ans);

	return 0;
}

 

你可能感兴趣的:(题解,贪心,大礼包,luogu,堆,堆排序,luogu,合并果子)