タイトルソース:loj
タイトル説明
Jiajiaの先生は、黒板に一連のn個の正の整数を書き、Jiajiaに次のことを行うように依頼しました。毎回2つの数字aとbを消去してから、一連の数字a * b +を追加します。 1.黒板に数字が1つ残るまでこれを続けます。この操作方法で最終的に得られるすべての数字の中で、最大が最大、最小が最小である場合、シーケンスの範囲はM = max-minとして定義されます。
Jiajiaは最終試験の準備で忙しいので、与えられたシリーズに対応する範囲を計算するのを手伝ってください
入力フォーマット
最初の
行で、正の整数nは、正の整数のシーケンスの長さを表します。次のn行で、各行に正の整数を入力します。
次の行には、データの終わりを示す0があります。
出力フォーマット
出力は、対応する範囲である1行のみです。
サンプル入力
3
1
2
3
0
サンプル出力
2
データ範囲とヒント
すべてのデータについて、0 <= n <= 50000で、すべてのデータ計算が32ビットの符号付き整数の範囲内にあることを確認します。
アイデア
最大と最小を求めて、直感的に貪欲を考える
最大を求める:
毎回番号のシーケンスで最小の2つを乗算する最小を求める:毎回番号のシーケンスで最大の2つを乗算する
このヤジでは、シーケンスの最小の2つを選択するたびに、priority_queueを使用します。最大の2つを選択する場合、元のシーケンスを最大から最小に並べ替えることは簡単に考えられます。乗数が大きいほど、他の乗数よりも確実に優れています。小さい方が大きい
コード
#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;
}