无法用复杂状态进行转移时改变计算方式;巧妙的整体考虑;压缩空间优化时间
传送门:$>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]); } ; }