【C++】「一本通 1.1 練習 1」數列極差

【來源】

一本通題庫-1427
LibreOJ-10005
vjudge

注意:一本通題庫和LibreOJ題意相同,但輸入格式不同。代碼以一本通題庫爲準。

【題目描述】

在黑板上寫了NN個正整數作成的一個數列,進行如下操作:每一次擦去其中的兩個數aabb,然後在數列中加入一個數a×b+1a×b+1,如此下去直至黑板上剩下一個數,在所有按這種操作方式最後得到的數中,最大的maxmax,最小的爲minmin,則該數列的極差定義爲M=maxminM=max−min

【輸入格式】

第一行,一個數爲NN;

第二行,NN個數。

【輸出格式】

輸出極差。

【輸入樣例】

3
1 2 3

【輸出樣例】

2

【數據範圍】

對於全部數據,0n500000\le n\le 50000,保證所有數據計算均在 3232 位有符號整數範圍內。

【解析1】

貪心。

求max:每次選取兩個最小的數。
求min:每次選取兩個最大的數。

【代碼1】

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;
 
typedef long long LL;

int const N=5e4+5;

int n;
int a[N],b[N];

int cmp(int a,int b) {
    return a>b;
}

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    for(int i=1; i<=n; i++) b[i]=a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=2; i<=n; i++) a[i]=a[i]*a[i-1]+1;
    int amin=a[n];
    sort(b+1,b+n+1);
    for(int i=2; i<=n; i++) {
        b[i]=b[i]*b[i-1]+1;
        sort(b+1,b+n+1);
    }
    int amax=b[n];
    int ans=amax-amin;
    printf("%d\n",ans);
    return 0;
}

【解析2】

貪心。

我們可以巧妙利用C++ STL裏面的greater和less,以及priority_queue。
對於greater()、less()兩個函數:
建堆的時候,默認是大根堆,第三個參數用greater()會變成小根堆。less()反之。
排序的時候,默認是從小到大,但是第三個參數用greater()會變成從大到小。less()反之。

用優先隊列代替數組。

兩種方法的時間複雜度是相似的。

【代碼2】

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <functional>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;
 
typedef long long LL;

int n;

priority_queue<int,vector<int>,greater<int> > q1;
priority_queue<int,vector<int>,less<int> > q2;

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        int a;
        scanf("%d",&a);
        q1.push(a);
        q2.push(a);
    }
    int amax=0;
    while(!q1.empty()) {
        if(q1.size()==1) {
            amax=q1.top();
            break;
        }
        int x=q1.top(); q1.pop();
        int y=q1.top(); q1.pop();
        q1.push(x*y+1);
    }
    int amin=0;
    while(!q2.empty()) {
        if(q2.size()==1) {
            amin=q2.top();
            break;
        }
        int x=q2.top(); q2.pop();
        int y=q2.top(); q2.pop();
        q2.push(x*y+1);
    }
    int ans=amax-amin;
    printf("%d\n",ans);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章