最小函数值 洛谷P2085

题目描述:

         有n个函数,分别为F1,F2,...,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*)。给定这些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题目分析:(MLE,TLE做法)看到题目我们第一眼肯定想到的是将每个函数枚举m次,然后对这n*m个数进行排序,输出前m个。代码如下:
 1 #include<cstdio>
 2 #include<algorithm>
 3 #define MAXSIZE 100000000+20
 4 #define MAXN 10000+20
 5 int a[MAXN],b[MAXN],c[MAXN];
 6 int num[MAXSIZE];
 7
 8 int main(){
 9     int n,m,k=1;
10     scanf("%d%d",&n,&m);
11     for(int i=1;i<=n;i++)
12         scanf("%d%d%d",&a[i],&b[i],&c[i]);
13     for(int i=1;i<=n;i++)
14         for(int j=1;j<=m;j++)
15             num[k++]=a[i]*j*j+b[i]*j+c[i];
16     std::sort(num+1,num+k);
17     for(int i=1;i<=m;i++)
18         printf("%d ",num[i]);
19     return 0;
20 }

     这样做的正确性是显而易见的:题目要求给出最小的M个数,这最小的M个数是由这N个函数生成的,最坏情况就是这M个数都由一个函数生成。那么即使这样,x的最大值也只是等于M,因为我们都知道:当二次函数y=ax2+bx+c(a>0)时,抛物线开口朝上,y随x增大而增大。所以当x1=i,x2=j(i,j∈N+,i<j)时y1<y2,所以我们对于同一个函数来说,x越小生成的数越小,这点在AC的算法中有很重要的作用。

   通过上面所说的,我们可以得知x最大值也只是等于M,也就是说我们的枚举区间就是1~m。我们需要对每个函数都枚举一遍,所以这一步的时间复杂度是O(n*m),最高是一亿,暂时还没超时,但是这是无序的,也就是说我们要将这n*m个数排序。

   假设我们用的是最快的快排,没被卡快排,那么这一步的时间复杂度就是O(n*m*log2(n*m));总体时间复杂度就是O(n*m*log2(n*m)),对于n=10000,m=10000,这个时间复杂度明显超时,况且我们还要花O(n*m)空间开销,这也是吃不消的。

 (AC做法)因为全部都算出来再排序输出必然超时,所以我们必须想办法减少算出来的值。在做出TLE且MLE的做法的时候,我们就证明了对于同一个函数而言,x越小生成的数越小,那我们不难画出下面这个表:

与x+1的关系 x的值 1 2 3 4 5 6 7 8
函数 < < < < < < < <
f1 < < < < < < < <
f2 < < < < < < < <
f3 < < < < < < < <
f4 < < < < < < < <
f5 < < < < < < < <
f6 < < < < < < < <
f7 < < < < < < < <
... < < < < < < < <

 



假设xi=1,xj=1时fi<fj则xi=1,xj=xj+1时fi<fj则当只存在fi和fj时xi=1时fi为最小值稍加思考,我们可以想到下面一种贪心算法:  一开始先取每个函数中x=1时的值,输出这中间最小的,然后将最小的更新为x=2时的情况,再输出最小的......  说到最小,就想到了用最小堆实现,代码如下:
 1 #include<cstdio>
 2 #include<algorithm>
 3 #define min(a,b) (((a)<(b))?(a):(b))
 4 using std::swap;
 5 struct h{
 6     int data;
 7     int place;
 8 }heap[10000+20];
 9 bool operator < (const h &X,const h &Y){           //重载小于号
10         return X.data<Y.data;
11     }
12 int a[10000+20],b[10000+20],c[10000+20];
13 int x[10000+20];
14 int n;
15 void put(int i){
16     while(i*2+1<=n){
17         if(min(heap[i*2],heap[i*2+1])<heap[i]){   //比较左儿子和右儿子
18             if(heap[i*2]<heap[i*2+1]){
19                 swap(heap[i*2],heap[i]);
20                 i*=2;
21             }else{
22                 swap(heap[i*2+1],heap[i]);
23                 i*=2;
24                 i++;
25             }
26         }else
27             break;
28     }if(i*2<=n&&heap[i*2]<heap[i]){
29         swap(heap[i*2],heap[i]);
30         i*=2;
31     }
32 }
33
34 int main(){
35     int m;
36     scanf("%d%d",&n,&m);
37     for(int i=1;i<=n;i++)
38         scanf("%d%d%d",&a[i],&b[i],&c[i]);
39     for(int i=1;i<=n;i++){
40         x[i]=1;                                          //保存每个函数的x用到了几
41         heap[i].data=a[i]+b[i]+c[i];                     //当x=1的情况
42         heap[i].place=i;
43     }
44     for(int i=n;i>=1;i--){
45         put(i);                                           //建堆
46     }
47     for(int i=1;i<=m;i++){
48         printf("%d ",heap[1].data);
49         int &k=heap[1].place;
50         heap[1].data=heap[1].data+2*a[k]*x[k]+a[k]+b[k];    //自己去算,不想讲,初二数学--完全平方式
51         x[heap[1].place]++;
52         put(1);
53     }
54     return 0;
55 }
时间复杂度O((n+m)log2n),最坏情况20000*log2(10000)≈280000不会超时空间复杂度O(n)最坏10000,约0.04MB,离上限128MB很远。


时间: 2024-11-11 17:05:52

最小函数值 洛谷P2085的相关文章

洛谷 P2764 LibreOJ 6002 最小路径覆盖问题

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务:

?Luogu P2085 最小函数值

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,Bi<=100,Ci<=10 000. 输出格式: 输出数据:输出将这n个函数所有可以生成的函数值排序后的前m个元素.

P2085最小函数值(优先队列)

P2085 最小函数值(minval) 题目描述 有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,Bi<=100,Ci<=10 000. 输出格式: 输出数据:输出将这n个函数所有可以生成的函数值排序

LGOJ P2085 最小函数值

P2085 最小函数值 这题好水--但是还是写一写吧-- 問題の解 用\(now[i]\)记录使得当前状态下\(f_i(x)\)取得最小值的自变量的值. 初始化: 初始状态,我们有\(n\)个二次函数\(f(x)=A_ix^2+B_ix+C_i,x \in \mathbb{N}^+\); 对称轴\(- \frac{B_i}{2A_i} \in (- \infty , 1)\)则\(now[i]=1\): 对称轴\(- \frac{B_i}{2A_i} \in [1, \infty )\)则\(n

[题解]洛谷比赛『期末考后的休闲比赛2』

[前言] 这场比赛已经结束了有几天,但我各种忙,虽然AK但还是没来得及写题解.(我才不会告诉你我跑去学数据结构了) T1 区间方差 (就不贴题好了) 首先可以推公式(我们可以知道,线段树然而并不能通过初中学过的方差公式在log(L)内求出方差): (s2表示方差,L表示区间长度,xi表示区间的每一项,最后一个x上画了一根线表示这些数据的平均数) 用二项式定理完全平方公式可得: 再次展开: 另外,再代入以下这个 得到了: 然后继续吧.. 然后duang地一声合并同类项,于是我们得到了: 然后可以高

洛谷 P3227 BZOJ 3144 [HNOI2013]切糕

题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑且和谐.于是她找到你,希望你能帮她找出最好的切割方案. 出于简便考虑,我们将切糕视作一个长 P.宽 Q.高 R 的长方体点阵.我们将位于第 z层中第 x 行.第 y 列上(1≤x≤P, 1≤y≤Q, 1≤z≤R)的点称为(x,y,z),它有一个非负的不和谐值 v(x,y,z).一个合法的切面满足以下两个条件: 与每个纵轴(一共有 P*Q 个纵轴)有且

洛谷P1848 [USACO12OPEN]书架Bookshelf

当农夫约翰闲的没事干的时候,他喜欢坐下来看书.多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书. 每本书 i 都有宽度 W(i) 和高度 H(i).书需要按顺序添加到一组书架上:比如说,第一层架子应该包含书籍1 ... k,第二层架子应该以第k + 1本书开始,以下如此.每层架子的总宽度最大为L(1≤L≤1,000,000,000).每层的高度等于该层上最高的书的高度,并且整个书架的高度是所有层的高度的总和,因为它们都垂直堆叠. 请帮助农

【洛谷】【洛谷月赛】4月月赛Round 1/2

洛谷月赛"月"来"月"丧了,一月更比一月丧,做得我十分不"月"-- 4月的两轮月赛,都只会T1,就写一下吧,等待后续更新-- 先看看Round1的T1: [R1T1] 网址:点我 [题意简述] 给定一个长度为n的序列,其中的元素均是1~m之间的正整数. 要求从中选出k个数,交换它们的位置,其他未被选中的数保持不变,使得变换后的序列中,相等的数总是排在一段连续区间. 要求最小化k. 1<=n<=105,1<=m<=20 [思

洛谷P1519 穿越栅栏 Overfencing

P1519 穿越栅栏 Overfencing 69通过 275提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 USACO是100分,洛谷是20分 为什么只有十分 题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路.给定迷宫的宽度W(1<=W<=38)及高度H(1<=H&