【貪心,堆】數列極差問題

問題 F: 【貪心】數列極差問題

時間限制: 1 Sec 內存限制: 64 MB
[提交] [狀態]
題目描述
“我就說你在忽悠我吧,我剛纔問了昆士蘭大學的好多魔法師,他們根本就沒有一個人想過做什麼時間旅行的實驗,但搞笑的是,他們居然對你的理論很感興趣,想找個時間和你做進一步的討論。哎,我還以爲他們和我一樣聰明呢,想不到這麼容易上當受騙。”小墨老師擺出一幅你騙不了我的表情。

“唉,你太自以爲是了,這樣吧,你先把這道數列極差問題發給他們,如果他們能有所領悟,那我會找時間和他們討論一下時間旅行的可行性的。”李旭琳邊說邊在黑板上寫了N個正整數組成的一個數列,並進行如下操作:每次擦去其中的兩個數a和b,然後在數列中加入一個數a×b+1,如此下去直至黑板上剩下一個數,在所有按這種操作方式最後得到的數中,最大的爲max,最小的爲min,則該數列的極差定義爲M=max-min。

現在請你編程,對於給定的數列,計算極差。
輸入
輸入包含多個測試集。每個測試集的第一個數N表示 正整數序列長度(0≤N≤50000),隨後是N個正整數。N爲0表示輸入結束。
輸出
每個結果一行。
樣例輸入 Copy
3
1 2 3
0
樣例輸出 Copy
2
提示
每次合併最小的兩個最後得到的是最大的,而每次合併最大的兩個的時候最後得到的是最小的。
例如有6個數,即8 6 5 9 7 1
則min求值過程爲: max求值過程爲:
73 7 6 5 1     6 6 7 8 9
512 6 5 1     37 7 8 9
3073 5 1      37 57 9
15366 1      334 57
15367      19039
ans=19039-15367=3672

分析:

首先考慮有三個正整數
a,b,c,且a<b<c。
那麼將會有三種不同的組合方法:
(ab+1)c+1=abc+c+1
(ac+1)b+1=abc+b+1
(bc+1)a+1=abc+a+1
顯然先取兩個小數最後結果最大,取兩個大數結果最小。
所以只需要維護一個大根堆和一個小根堆分別操作,直到兩個堆內都只剩一個數,再將兩者相減即爲此題答案。

我的代碼:

#include <cstdio>
#include <iostream>
#include <queue>

using namespace std;

priority_queue<int> gq;
priority_queue<int, vector<int>, greater<int> > lq;

int main()
{
    int n,x;
    while(scanf("%d",&n) && n)
    {
        while(gq.size()>0)
        {
            gq.pop();
        }
        while(lq.size()>0)
        {
            lq.pop();
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            gq.push(x), lq.push(x);
        }
        while(gq.size() > 1)
        {
            int a = gq.top();
            gq.pop();
            int b = gq.top();
            gq.pop();
            gq.push(a*b+1);
        }
        while(lq.size() > 1)
        {
            int a = lq.top();
            lq.pop();
            int b = lq.top();
            lq.pop();
            lq.push(a*b+1);
        }
        printf("%d\n", lq.top() - gq.top());
    }
    return 0;
}

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