トピックリンク:配列
分析:
- 各シーケンスから順番に番号を選択するには、上位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;
}