該題目給定了我們一些二次函式,不過這個函式只取了橫座標為正整數部分的值,並且三個係數都為正數,通過代數證明或者影象對稱軸分析,都可以肯定,該函式在其定義域(正整數)上,單調遞增且恆大於0。
接下來我們再看到題目要求,求這些函式所生成的所有函式值中最小的m個。
比較暴力的方法是從1開始迴圈(可能不是最暴力的方法),將1代入所有的函式中,分別得到n個函式值,然後再迴圈到2,按照這樣的方法再來一遍,又有n個函式值,又因為這些都是在其定義域內單調遞增的函式,那麼首先可以確定1中所有小於等於2中最小函式值的函式值,然後接著按照上述方案做,迴圈到k時,可以確定從x=1到x=k-1中所有小於等於x=k中最小函式值的函式值,直到確定了m個值。
但是這樣的話,思想實在簡單,絕配暴力演算法一名。暴力之處在於:一、每次求出\(o(n)\)的函式值,耗費\(o(n)\)的空間,最壞情況下要求\(o(mn)\)次,花費\(o(mn)\)空間,而資料一大,時間空間無疑是要超出範圍的;二、每次迴圈求出的函式值得進行排序,如果不排序,那個運算量不敢恭維,假設使用\(\theta (nlgn)\)複雜度排序,那麼也需要花\(\theta (mnlgn)\)的複雜度;三、再加上每次需要計算x=k中的最小函式值與前面k-1中所有的函式值進行比較,這樣在最壞情況下時間代價為:
\[o(\sum _ ^ (kn))=o((m-1)mn/2)=o(m^2n)
\]那麼,總的算來,就會消耗\(o(o(mn)+\theta (mnlgn)+o(m^2n))=o(m^2n)\)的時間代價,極其暴力!而且空間上的消耗也是巨大的!
那麼,我們該如何優化呢?
其實,大家看到函式解析式極其定義域就不難知道,他實際上是給了我們n串排好序的陣列,只是每個陣列中下標與其值存在一定的對應關係。我們由上面所說的可知,對於每個陣列,它們的最小值所在的下標都是1。現在,我們可以想象一下,每個陣列都有乙個箭頭,每個箭頭都指向1,然後在所有箭頭指向的函式值中,找到最小的那個,此時已經找到了1個最小函式值。接著,剛才輸出來的值所對應的箭頭就要向後移,指向x=2,然後再去和其他箭頭指向的函式值比較,以此類推。下面的兩個圖形象地展現了一部分操作過程。
那麼,現在我們需要將文字描述轉化為程式思路。
首先我們需要用三個陣列存a、b、c的值,然後需要乙個cmin存當前最小值,最後只需要拿乙個陣列f來表示每個函式中的那個「箭頭」所指的位置,那麼箭頭所指的函式值就會是\(a[k]f[k]^2+b[k]f[k]+c[k]\),至此,思路就很明了了。
下面是我寫的程式,很簡單,最長耗時測試點用了344ms,沒超時。
#include using namespace std;
int main()
for(i=0;i該程式的時間複雜度為\(\theta (mn)\)。
大家也許會發現,這裡每次都重複計算了很多函式的值,浪費了很多時間,那有沒有辦法針對這一問題進行優化呢?答案是肯定的。
對於上述問題的優化方法,比較好的是用堆來做。思路是這樣的:首先,我們可以在所有「箭頭」指向1的時候,對所有箭頭對應的函式值建立小根堆;然後,每次從堆頂取走那個數,並將其所對應的「箭頭」指向下乙個函式值,然後把這個新的函式值代替那個取走的函式值放在堆頂,並自頂向下維護堆(大家可以證明一下,一直這樣操作下去,堆的性質恆成立)。下面是我的參考程式:
#include using namespace std;
struct dui
a[10010];
int heap_size;//堆的大小
void change(int m, int n)//自己寫的交換函式
void min_heapify(int i)
int main()
heap_size=n;
build_heap();
for(i=0; i該程式的時間複雜度為\(\theta (nlgn)\)或\(\theta (mlgn)\)。程式在洛谷上測試通過了,並且最大耗時的測試點耗時8ms。
最小函式值
給n個函式。fi x ai x 2 bi x ci 給定這些ai bi和ci,請求出所有函式的所有函式值中最小的m個。3 10 4 5 3 3 4 5 1 7 1 9 12 12 19 25 29 31 44 45 54 維護乙個小根堆,裡面的值為,按照要求每次輸出堆頂,並將堆頂函式中的x加1再下調...
最小函式值
最小函式值 time limit 1000ms memory limit 65536k total submit 121 accepted 54 description 問題描述 有n個函式,分別為f1,f2,fn。定義fi x ai x 2 bi x ci x n 給定這些ai bi和ci,請求出...
最小函式值
題目描述 有n個函式,分別為f1,f2,fn。定義fi x aix 2 bix ci x n 給定這些ai bi和ci,請求出所有函式的所有函式值中最小的m個 如有重複的要輸出多個 輸入格式 輸入資料 第一行輸入兩個正整數n和m。以下n行每行三個正整數,其中第i行的三個數分別位ai bi和ci。ai...