題意:
兩個都含有n個元素的陣列a,b, 求 a[i]+b[j] ( i , j < n ) 的前 m個最小值(m < n)
解題思路:
假定a,b陣列都有序,則我們有下面的結論:
a_1 + b_1 <= a_1 + b_2 <= ... <= a_1 + b_n
a_2 + b_1 <= a_2 + b_2 <= ... <= a_2 + b_n
a_n + b_1 <= a_n + b_2 <= ... <= a_n + b_n
那麼我們就可以得出乙個 n*n 的矩陣.如下形式
a(1,1), a(1,2), ..., a(1,n)
a(2,1), a(2,2), ... ,a(2,n)
a(n,1), a(n,2), ... ,a(n,n)
我們知道,第乙個最小的必定是 a(1,1),
而且. 從 a(1,1) 位置往下(a(2,1)) 或者 往右(a(1,2)), 其值必定增大.
但是我們又不知道 a(1,2) 與 a(2,1) 之間的關係.
不過, 我們可以想到:
若第k小的數是 a(i,j), 則第 k+1小的數可能是a(i+1,j)與a(i,j+1) 之間的數.
因為還有可能是在 其他的 a( a,b ) 的下或者右中..
又因為 我們只需要取前 m <= n 個數.所以我們使用乙個容器,讓裡頭儲存n個數.
每次從容器中取出乙個最值( a(a,b) ), 則再將其下方( a(a+1,b) ),與右邊( a(a,b+1) ) 的值放入容器中.
這個容器我們可以選 堆/優先佇列:
編碼細節:
我們可以預處理把 a(1,1), a(1,2), ...,a(1,n) 這n個數放到堆中, 每次取出最小的a(a,b)時,
則只需要將 a(a+1,b) 加入到堆即可. 因為 a(a,b+1)已經在堆中了.
這樣.始終維護著堆中包含n個元素. 當輸出滿足m個了就結束即可.
演算法時間複雜度:
優先佇列的 插入與刪除操作都是 log(n). 總共n個元素.
則總體時間複雜度: nlogn
view code
#include#include#include
#include
#include
using
namespace
std;
const
int n = 4e5+10
;int
a[n], b[n], res[n];
intn, m;
struct
node
}node;
priority_queue
q;int
main()
for(int i = 0; i < m; i++)
}return0;
}
2013第四場多校
多校第四場 6題,打得最好的一場多校。還是cjboy給力。本場比賽我基本上沒什麼貢獻,搞04一搞就是一下午。最後看了09覺得只有狀態壓縮,不知道怎麼優化。1004 圖論,強聯通分量 0 一開始推理的時候思路很清晰,但是接著就腦殘了,沒怎麼細想就直接去套樣例。以為得到了正確的解法,只是需要乙個特判。然...
2013多校第四場 E題 ZZ的研究
題意 有n n 1000 個數 a1,a2,an,ai 10 15,取其中部分組合相乘的到數是乙個完全平方數.求方案總數.其中保證 ai 不包含大於500的質因子.解題思路 解決本題需要有,線性代數基礎.涉及到關於矩陣的初等變換與高斯消元.求解齊次方程.首先考慮,乙個數 x p1 e1 p2 e2 ...
2015 多校第四場 XYZ and Drops
include include include include using namespace std struct node const int maxn 210 vector pair iterator it int d 5 2 int r,c 直接暴力模擬,注意題意 若水珠原來大小為3,恰好某...