UVA - 11997 思維
阿新 • • 發佈:2018-02-19
整數 最小 define span 最大 思維 tar sum 元素
UVA - 11997
題意:有K個整數數組,各包含K個元素。在每個數組中取一個元素加起來,可以得到k^k個和。求這些和中最小的K個值。
tags:思維,大白書189
簡化版:兩個數組 A[]、 B[],有 k*k 個和,怎麽快速求出前 k 小和 ?
數組排序後,對於 s1= A[i]+B[j] ,它的下一個最大的和就是 A[i]+B[j+1] = s1-B[j]+B[j+1] 。 所以優先隊列優化一下,就可以實現 O(n*log(n)) 。
對於 k 個數組,我們只要兩兩合並就可以了。
#include<bits/stdc++.h> using namespacestd; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedeflong long ll; const int N = 805; int k, a[N][N]; struct Item { int id, sum; bool friend operator<(Item ca, Item cb) { return ca.sum > cb.sum; } }; priority_queue< Item > q; void Merge(int* A, int* B) { while(!q.empty()) q.pop(); rep(i,1,k) q.push((Item){ 1, A[i]+B[1] }); rep(i,1,k) { Item u=q.top(); q.pop(); A[i]=u.sum; if(u.id<k) q.push((Item){ u.id+1, u.sum-B[u.id]+B[u.id+1] }); } } int main() { while(~scanf("%d", &k)) { rep(j,1,k) scanf("%d", &a[1][j]); sort(a[1]+1, a[1]+1+k); rep(i,2,k) { rep(j,1,k) scanf("%d", &a[i][j]); sort(a[i]+1, a[i]+1+k); Merge(a[1], a[i]); } rep(j,1,k) printf("%d%c", a[1][j], " \n"[j==k]); } return 0; }
UVA - 11997 思維