题目描述:

         有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个。代码如下:
 #include<cstdio>
#include<algorithm>
#define MAXSIZE 100000000+20
#define MAXN 10000+20
int a[MAXN],b[MAXN],c[MAXN];
int num[MAXSIZE]; int main(){
int n,m,k=;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
num[k++]=a[i]*j*j+b[i]*j+c[i];
std::sort(num+,num+k);
for(int i=;i<=m;i++)
printf("%d ",num[i]);
return ;
}

     这样做的正确性是显而易见的:题目要求给出最小的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时的情况,再输出最小的......
  说到最小,就想到了用最小堆实现,代码如下:
 #include<cstdio>
#include<algorithm>
#define min(a,b) (((a)<(b))?(a):(b))
using std::swap;
struct h{
int data;
int place;
}heap[+];
bool operator < (const h &X,const h &Y){ //重载小于号
return X.data<Y.data;
}
int a[+],b[+],c[+];
int x[+];
int n;
void put(int i){
while(i*+<=n){
if(min(heap[i*],heap[i*+])<heap[i]){ //比较左儿子和右儿子
if(heap[i*]<heap[i*+]){
swap(heap[i*],heap[i]);
i*=;
}else{
swap(heap[i*+],heap[i]);
i*=;
i++;
}
}else
break;
}if(i*<=n&&heap[i*]<heap[i]){
swap(heap[i*],heap[i]);
i*=;
}
} int main(){
int m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=;i<=n;i++){
x[i]=; //保存每个函数的x用到了几
heap[i].data=a[i]+b[i]+c[i]; //当x=1的情况
heap[i].place=i;
}
for(int i=n;i>=;i--){
put(i); //建堆
}
for(int i=;i<=m;i++){
printf("%d ",heap[].data);
int &k=heap[].place;
heap[].data=heap[].data+*a[k]*x[k]+a[k]+b[k]; //自己去算,不想讲,初二数学--完全平方式
x[heap[].place]++;
put();
}
return ;
}
时间复杂度O((n+m)log2n),最坏情况20000*log2(10000)≈280000不会超时
空间复杂度O(n)最坏10000,约0.04MB,离上限128MB很远。


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

  1. P2085 最小函数值 洛谷

    https://www.luogu.org/problem/show?pid=2085 题目描述 有n个函数,分别为F1,F2,...,Fn.定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*) ...

  2. 洛谷P2085 最小函数值(minval)

    P2085 最小函数值(minval) 218通过 487提交 题目提供者该用户不存在 标签堆高级数据结构 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 暂时没有讨论 题目描述 有n个函数, ...

  3. 洛谷P2085最小函数值题解

    题目 首先我们先分析一下题目范围,\(a,b,c\) 都是整数,因此我们可以得出它的函数值在\((0,+\infty )\)上是单调递增的,,然后我们可以根据函数的性质,将每个函数设置一个当前指向位置 ...

  4. [洛谷P2085]最小函数值

    题目大意:有n个函数,分别为F1,F2,...,Fn.定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*).给定这些Ai.Bi和Ci,要求出所有函数的所有函数值中最小的m个(如有重复的要输出多个 ...

  5. 洛谷P2085——最小函数值

    题目描述 有n个函数,分别为\(F_1,F_2,...,F_n\).定义\(F_i(x)=A_i*x^2+B_i*x+C_i (x∈N*)\).给定这些\(A_i.B_i和C_i\),请求出所有函数的 ...

  6. 洛谷 P2085 最小函数值

    目录 题目 思路 \(Code\) 题目 戳 思路 首先这些函数全部单带递增,因为\(a\),\(b\),\(c\)都是正整数. 我们将全部的函数的\(x\)为\(1\)时的函数值放入优先度列(小根堆 ...

  7. P1576 最小花费 洛谷

    https://www.luogu.org/problem/show?pid=1576 题目背景 题目描述 在n个人中,某些人的银行账号之间可以互相转账.这些人之间转账的手续费各不相同.给定这些人之间 ...

  8. 洛谷P4014 分配问题【最小/大费用流】题解+AC代码

    洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...

  9. 洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】分析+题解代码

    洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication[最小割]分析+题解代码 题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流. ...

随机推荐

  1. 使用yum安装cmake

    一.搜索yum源中的CMake,查看源中最新的版本是什么,使用命令[root@localhost ~]# yum search cmake ,如果搜索出的结果过多可以配合grep命令来控制搜索结果. ...

  2. SQLHELPER 帮助类

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  3. 2017-3-2 C#基础 集合

    要使用集合必须先引用命名空间,using System.Collections; 集合与数组的不同: 数组:同一类型,固定长度集合:不同类型,不固定长度 集合主要分为六大类:普通集合,泛型集合,哈希表 ...

  4. RabbitMQ(从安装到使用)

    RabbitMQ 一,RabbitMQ简单介绍: RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Messa ...

  5. nginx配置之深入理解

    继上一篇<debian+nginx配置初探--php环境.反向代理和负载均衡>成功之后,有点小兴奋,终于不用整lvs那么复杂来搞定负载,但还是有很多概念没弄清楚. 什么是CGI.FastC ...

  6. [Selenium With C#学习笔记] Lesson-06 单选按钮

    作者:Surpassme 来源:http://www.jianshu.com/p/08ee1929875f 声明:本文为原创文章,如需转载请在文章页面明显位置给出原文链接,谢谢. 单选按钮通常用在需要 ...

  7. 1088: [SCOI2005]扫雷Mine

    1088: [SCOI2005]扫雷Mine Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1635  Solved: 979[Submit][Sta ...

  8. Archlinux 升级 pacman 时遇到的问题及其解决

    这是 Archlinux 升级时经常碰到的老问题.提示如下 问题来了 # yaourt -Syua ==> 警告:使用 root 用户构建软件包存在风险. 请使用非特权用户运行 yaourt . ...

  9. RecyclerView 设置item间隔的方法

    RecyclerView大家常用,但是如何给加载出来的item增加间隔很多人都不知道,下面是方法,直接上代码了: LinearLayoutManager layoutManager = new Lin ...

  10. Redhat

    vm1 port:192.168.210.102 user:root;pwd:123456 user:openflowpwd:openflowKkm09!q esx4.1 server 安装一.修改I ...