洛谷P2085 最小函式值(優先佇列)

2022-04-30 19:15:10 字數 1140 閱讀 3194

給定\(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));

//print

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...