給定\(n\)個二次函式:\(f(x)=ax^2+bx+c\),保證\(a,b,c,x\)均為正整數且\(a\leq10,b\leq100,c\leq10000\)。請輸出前\(m\)大的函式值。
有點難說,直接上題目鏈結吧
顯然,\(f(x)\)是單調遞增函式,肯定要用到堆(優先佇列)。
直接每個函式把前\(m\)個扔進去,然後在整個佇列裡面輸出前\(m\)個就行了。這種複雜度為\(o((nm)log(nm))\),顯然超時。
不妨令\(g(x)=x^2+x+1,h(x)=10x^2+100x+10000\),則\(g(x)\leq f(x)\leq h(x)\)。
假設\(g(x)\)的第k項必然大於所有函式值的總集合構成的單調遞公升數列的第m項,那麼\(g(k)>h(\frac)\)
解得\(k\geq\sqrt)^2+100\frac+9999}\)(必要解,非充分解)
綜上可以將複雜度壓至\(o(t log t)\),其中\(t=kn=\sqrt\leq 10^6\),降到了乙個可以接受的範圍內。
**如下:
#includeusing namespace std;
const int n=10010,m=10010;
priority_queue,greater>q;
int n,m,a[n],b[n],c[n];
inline int calc(int i,int x)
int main()
{ //read
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
int k=sqrt(10*m*m/n/n+100*m/n+9999)+1;
//calc
for(int x=1;x<=k;++x)
for(int i=1;i<=n;++i)
q.push(calc(i,x));
for(int i=1;i都將\(f_i(1)\)扔進堆裡面,然後取出最小的那項,然後看下它是第幾個函式,然後將它的下乙個後繼(例如\(f_i(x)\)的下乙個後繼是\(f_i(x+1)\))扔進去,以此類推,取滿\(m\)個為止。
**略,洛谷題解裡面蠻多的(逃)。
洛谷 P2085 最小函式值 優先佇列
題目描述 有n個函式,分別為f1,f2,fn。定義fi x aix 2 bix ci x n 給定這些ai bi和ci,請求出所有函式的所有函式值中最小的m個 如有重複的要輸出多個 輸入格式 輸入資料 第一行輸入兩個正整數n和m。以下n行每行三個正整數,其中第i行的三個數分別位ai bi和ci。ai...
洛谷 P2085 最小函式值
有n個函式,分別為f1,f2,fn。定義fi x ai x 2 bi x ci x n 給定這些ai bi和ci,請求出所有函式的所有函式值中最小的m個 如有重複的要輸出多個 輸入格式 輸入資料 第一行輸入兩個正整數n和m。以下n行每行三個正整數,其中第i行的三個數分別位ai bi和ci。ai 10...
P2085 最小函式值 洛谷
有n個函式,分別為f1,f2,fn。定義fi x ai x 2 bi x ci x n 給定這些ai bi和ci,請求出所有函式的所有函式值中最小的m個 如有重複的要輸出多個 輸入格式 輸入資料 第一行輸入兩個正整數n和m。以下n行每行三個正整數,其中第i行的三個數分別位ai bi和ci。ai 10...