hdu 5548 sort 2016青島區域賽網絡賽 二分+隊列優化

傳送門:hdu 5548 sort

這個題目的標準複雜度是o(n*lgn),據說如果多乘一個lgn優化一個輸入還是可以過得!也就是使用優先隊列的做法!
這個題目還有一個坑點就是不能每次只是貪心,就比如說枚舉到k=4的時候1,2,3,4,5這個數列的最小值是先把前兩個合併變爲數列3,3,4,5然後在進行合併纔是最少的花費,這樣的花費是3+15=18,然而如果按照貪心的思路去做,第一次先枚舉前四個那麼第一次過後數列就變爲10,5這樣的花費就變爲10+10+5=25了,怎麼才能保證結果是花費的最小呢?我們只需要保證最後一次取得是k個就可以了!那麼下一個問題就是怎麼保證最後一次取得是k個呢?
我們來想一下如果按照每次都是取k個來說,每次失去的就是k-1個數,所以我們只需要第一次合併(N-1)%(k-1)+1,{(N-1)%(k-1)這個值爲0的話就不用+1了}就可以了!
那怎麼保證複雜度呢?我們只需要申請兩個隊列就可以,把每次合併完的放到新的隊列裏面,每次取得時候取得是這個兩個隊列的最小值就可以!這樣就nlgn得複雜度了!

AC代碼

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MX = 100000 + 5;
const LL INF = 1e18;

int seq[MX << 2], N;
LL T;

bool check(int n) {
    while(!que.empty()) que.pop();
    while(!tq.empty())  tq.pop();
    int fl = (N - 1) % (n - 1);
    int md = fl ? fl + 1 : 0;
    int st = N + 1 - (n - md);
    if(fl) for(int i=1;i<=n-md;i++) que.push(0);
    for(int i = 1; i <= N ; i++) que.push(seq[i]);
    LL ans = 0;
    while((que.size() + tq.size()) > 1) {
        LL tmp = 0;
        for(int i = 0; i < n; i++) {
            LL A = INF, B = INF;
            if(que.empty() && tq.empty())  {
                ans += tmp;
                goto END;
            }
            if(!que.empty()) A = que.front();
            if(!tq.empty())  B = tq.front();
            if(A <= B) {
                tmp += A;
                que.pop();
            } else {
                tmp += B;
                tq.pop();
            }
        }
        ans += tmp;
        tq.push(tmp);
    }
END:;
    if(ans > T) return false;
    return true;
}

void solve() {
    int l = 2, r = N, mid,ans=0;
    while(l<=r) {
        mid  = (l + r) >> 1;
        if(check(mid)) {
            ans  = mid;
            r = mid-1;
        } else l = mid+1;
    }
    printf("%d\n", ans);
}
int main(void) {
    int _;
    //freopen("in.txt", "r", stdin);
    cin >> _;
    while(_--) {
        scanf("%d%I64d", &N, &T);
        for(int i = 1; i <= N; i++) scanf("%d", &seq[i]);
        sort(seq +1, seq +1 + N );
        solve();
    }
    return 0;
}
發佈了215 篇原創文章 · 獲贊 197 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章