题目来源:loj
题目描述
佳佳的老师在黑板上写了一个由n个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数a和b,然后在数列中加入一个数a*b+1 ,如此下去直至黑板上剩下一个数为止,在所有按这种操作方式最后得到的数中,最大的为max ,最小的为 min, 则该数列的极差定义为M=max-min 。
由于佳佳忙于准备期末考试,现请你帮助他,对于给定的数列,计算出相应的极差
输入格式
第一行为一个正整数n 表示正整数序列的长度;
在接下来的 n行中,每行输入一个正整数。
接下来的一行有一个0,表示数据结束。
输出格式
输出只有一行,为相应的极差 。
样例输入
3
1
2
3
0
样例输出
2
数据范围与提示
对于全部数据,0<=n<=50000,保证所有数据计算均在32位有符号整数范围内。
思路
求最大最小,直觉想到贪心
求max:每次选取数列中最小的两个相乘
求min:每次选取数列中最大的两个相乘
就这个亚子,每次选取数列中最小的两个,我用了priority_queue,至于选最大的两个,很容易可以想到给原来的数列从大到小排序,大的乘大的绝对是比其他小的还要大
code
#include<bits/stdc++.h>
using namespace std;
const int N=50010;
int n,a[N],b;
priority_queue<int,vector<int>,greater<int> >q;//小根堆
void init()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&a[i]);
q.push(a[i]);
}
scanf("%d",&b);
}
int cmp(int x,int y) {
return x>y; }
int work_max()
{
int tmp;
while (!q.empty())
{
tmp=q.top();
q.pop();
tmp=tmp*q.top()+1;
q.pop();
if (q.empty()) break;
q.push(tmp);
}
return tmp;
}
int work_min()
{
sort(a+1,a+1+n,cmp); //从大到小
int anss=a[1];
for (int i=2;i<=n;i++)
anss=anss*a[i]+1;
return anss;
}
int main()
{
init();
int maxx=work_max();
int minn=work_min();
cout<<maxx-minn<<endl;
return 0;
}