シーケンス(カセット/クイックセレクト)

トピックリンク:配列
分析:

  • 各シーケンスから順番に番号を選択するには、上位n個の合計のみを維持する必要があります
  • 上位n個の数と新しいシーケンスn個の数がペアで追加され、合計n 2 n ^ 2n2番号
  • このn2 n ^ 2からの場合n2つの数値から上位nを選択すると、クイック選択を使用する複雑さの合計はO(mn 2)O(mn ^ 2)です。O m n2、ヒープ使用するにはO(mn 2 logn)O(mn ^ 2logn)が必要ですO m n2 logn、とにかくタイムアウトします
  • 実際、n 2 n ^ 2を考慮する必要はありません。n2つの数値、考慮する必要があるのはn(1 + 1 2 + 1 3 +…+ 1 n)= O(nlogn)n(1 + \ dfrac12 + \ dfrac13 + \ cdots + \ dfrac1n)= O(nlogn)n 1+21+31++n1=O n l o g n 数、ヒープの合計時間計算量はO(mnlog(nlogn))O(mnlog(nlogn))O m n l o g n l o g n 、クイックセレクトを使用するとO(mnlogn)O(mnlogn)O m n l o g n 、後者は少し面倒で、書くのが面倒です。ヒープを使用するだけです。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

int n; /* number of elements per sequence */
int m; /* number of sequence */

int a[105][2005];
using pq_t = priority_queue<int, vector<int>, greater<int>>;

int main()
{
    
    
    int T; cin >> T;
    while (T--) {
    
    
        cin >> m >> n;
        for (int i = 0; i < m; ++i) {
    
    
            for (int j = 0; j < n; ++j) {
    
    
                scanf("%d", &a[i][j]);
            }
            sort(a[i], a[i]+n);
        }
        vector<int> v(a[0], a[0]+n);
        pq_t pq;
        for (int i = 1; i < m; ++i) {
    
    
            vector<int> tmp;
            for (int j = 0; j < n; ++j)
                for (int k = 0; k < n/(j+1); ++k)
                    tmp.push_back(v[j] + a[i][k]);
            pq = pq_t(tmp.begin(), tmp.end());
            v.clear();
            for (int cnt = 0; cnt < n; ++cnt) {
    
    
                v.push_back(pq.top());
                pq.pop();
            }
        }
        for (int x : v) printf("%d ", x); printf("\n");
    }
    system("pause");
    return 0;
}

おすすめ

転載: blog.csdn.net/w112348/article/details/111148105