无法用复杂状态进行转移时改变计算方式;巧妙的整体考虑;压缩空间优化时间

传送门:$>here<$

题意

Solution

问题的转化

序列合并问题是这道题的弱化版——也就是在这道题目里规定n=2。这样的问题做法是先分别排序,然后默认a[1]与b[1..n]相加得到的n个和为最小,然后分别用其他的和去更新。由于单调性,a[i]一旦不能满足就立即跳出,可以证明复杂度接近$O(nlog^2n)$

这道题变成了n行,而我们可以将其转化为两行的问题——将前n-1行看做一个子问题。由于保证了k<=m,因此每做完一次就将若干行合并为一行,反复迭代即可。

启示

问题的转化

利用所要求的条件转化问题。尤其是这种非常类似的。

my code

第一行要特判

/*By DennyQi 2019*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
;
const int INF = 0x3f3f3f3f;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
    ; ; register char c = getchar();
    '); c = getchar());
    , c = getchar();
    ) + (x<<) + c - '; return x * w;
}
int n,m,K;
int a[MAXN],b[MAXN],c[MAXN];
priority_queue <int, vector<int>, less<int> > H;
inline void Merge(){
    while(H.size()) H.pop();
    ; i <= m; ++i){
        H.push(a[] + b[i]);
    }
    ; i <= m; ++i){
        ; j <= m; ++j){
            if(a[i]+b[j] < H.top()){
                H.pop();
                H.push(a[i]+b[j]);
            }
            else{
                break;
            }
        }
    }
    ; --i){
        c[i] = H.top();
        H.pop();
    }
}
int main(){
    n = read(), m = read(), K = read();
    ; i <= n; ++i){
        ; j <= m; ++j){
            a[j] = read();
        }
        sort(a+,a+m+);
        ){
            ; j <= m; ++j){
                b[j] = a[j];
            }
            continue;
        }
        Merge();
        ; j <= m; ++j){
            b[j] = c[j];
        }
    }
    ; i <= K; ++i){
        printf("%d ",b[i]);
    }
    ;
}
05-08 08:08