【問題解決】シーケンスが極端に悪い

タイトルソース: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;
}

おすすめ

転載: blog.csdn.net/weixin_45485187/article/details/102798470