[CQOI2012]组装

LG传送门

首先有一个必须要能推的式子:设第\(i\)种零件选的生产车间位置为\(x _ i\),组装车间位置为\(x\), 则总的花费为

\[f(x) = \sum \limits _{i = 1} ^ n (x - x_i) ^ 2
\]

\[= n x^ 2 - 2 \sum \limits _{i = 1} ^ n x _ i x + \sum \limits _{i = 1} ^ n x _ i ^ 2
\]

这是一个关于\(x\)的二次函数, 在\(x = \frac {\sum \limits _{i = 1} ^n x_i}{n}\)时取得最小值\(\sum \limits _{i = 1} ^ n x _ i ^ 2 - \frac {\sum \limits _{i = 1} ^ n x _ i} {n}\)。做到这步,我们就可以获得前40分,只需要枚举每种零件选的生产车间,复杂度是指数级的。考虑贪心优化枚举的过程。

下面为了表述方便,设\(o = \sum \limits _ {i = 1} ^ n x _ i ^ 2\),\(e = \sum \limits _{i = 1} ^ n x _ i\)。

首先我们对于同一种零件的生产车间按坐标从小到大排序,每次枚举把某种零件的生产车间替换成他的下一个,这样是有一些情况枚举不到的,但事实上我们只要保证可能的情况都枚举到了就行了,于是贪心.

先给出贪心的结论:设一次替换用一个二元组\(\{x _ i, y _ i\}(x_i < y_i)\)来表示,如果我们先把表示替换的二元组按照\(x _ i + y _ i\)从小到大排序,这样就一定不会错过最优解。

下面证明这个结论:用反证法,假设我们这样做会错过最优解,那么一定存在\(\{x_1, y_1\}\)和\(\{x_2, y_2\}\)表示的替换使得\(x_1\)和\(y_2\)是满足最优解的条件,且替换\(\{x_1, y_1\}\)比替换\(\{x_2, y_2\}\)先进行。由于\(x_1\)是满足最优解的条件,而\(y_1\)不是,那么必有\(\frac {e} {n}\)(满足最优解的组装车间)\(< \frac {x_1+ y_1} {2}\)(二者之间线段的中点),这个结论是显然的(可以自己手玩)。同理有\(\frac {e} {n} > \frac {x_2 + y_2} {2}\),由此及上式得\(x_1 + y_1 > x_2 + y_2\),但我们已经事先排序保证\(x_1 + y_1 < x_2 + y_2\),矛盾。

实现起来就非常简单了,每次替换维护\(o\)和\(e\)的变化量,再用\(o - \frac {e ^ 2} {n}\)和\(e / n\)更新最小值和答案就行了。

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <vector>
  4. #include <algorithm>
  5. #define R register
  6. #define I inline
  7. #define B 1000000
  8. #define D double
  9. #define P pair <int, int>
  10. using namespace std;
  11. const int N = 10003;
  12. char buf[B], *p1, *p2;
  13. I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin),p1 == p2) ? EOF : *p1++; }
  14. I int rd() {
  15. R int f = 0, b = 1;
  16. R char c = gc();
  17. while ((c < 48 || c > 57) && c ^ 45)
  18. c = gc();
  19. if (c == 45)
  20. b = 0, c = gc();
  21. while (c > 47 && c < 58)
  22. f = f * 10 +(c ^ 48), c = gc();
  23. return b ? f : ~f + 1;
  24. }
  25. vector <int> f[N];
  26. vector <pair <int, int> > g;
  27. I D pow(D x) { return x * x; }
  28. I int cmp(P x, P y) { return x.first + x.second < y.first + y.second; }
  29. int main() {
  30. R int n = rd(), m = rd(), i, j, s, x, y;
  31. D o = 0, e = 0, del, tmp, ans;
  32. for (i = 1; i <= m; ++i)
  33. x = rd(), y = rd(), f[y].push_back(x);
  34. for (i = 1; i <= n; ++i) {
  35. s = f[i].size(), sort(&f[i][0], &f[i][0] + s);
  36. for (j = 1; j < s; ++j)
  37. g.push_back(make_pair(f[i][j - 1], f[i][j]));
  38. }
  39. for (i = 1; i <= n; ++i)
  40. o += pow(f[i][0]), e += f[i][0];
  41. tmp = o - pow(e) / n, ans = e / n, s = g.size(), sort(&g[0], &g[0] + s, cmp);
  42. for (i = 0; i < s; ++i) {
  43. o += pow(g[i].second) - pow(g[i].first), e += g[i].second - g[i].first;
  44. if ((del = o - pow(e) / n) < tmp)
  45. tmp = del, ans = e / n;
  46. }
  47. printf("%.4lf", ans);
  48. return 0;
  49. }

[CQOI2012]组装 贪心的更多相关文章

  1. 【BZOJ2666】[cqoi2012]组装 贪心

    [BZOJ2666][cqoi2012]组装 Description 数轴上有m个生产车间可以生产零件.一共有n种零件,编号为1~n.第i个车间的坐标为xi,生产第pi种零件(1<=pi< ...

  2. Luogu3162 CQOI2012 组装 贪心

    传送门 如果提供每一种零件的生产车间固定了,那么总时间\(t\)与组装车间的位置\(x\)的关系就是 \(t = \sum (x-a_i)^2 = nx^2-2\sum a_ix + \sum a_i ...

  3. [CQOI2012]组装 (贪心)

    CQOI2012]组装 solution: 蒟蒻表示并不会模拟退火,所以用了差分数组加贪心吗.我们先来看题: 在数轴上的某个位置修建一个组装车间 到组装车间距离的平方的最小值. 1<=n< ...

  4. luogu P3162 [CQOI2012]组装

    传送门 mdzz,为什么这题有个贪心的标签啊qwq 首先考虑每一种车间,对于每相邻两个车间,在中点左边那么左边那个会贡献答案,在右边就右边那个更优 所以总共会有m-1个这样的分界中点,然后最多有m+1 ...

  5. BZOJ 2666: [cqoi2012]组装

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2666 题意:n种零件,m个位置,每个位置有一种零件.求一个位置x,使得cost(1 ...

  6. P3162 [CQOI2012]组装

    传送门 退火大法好 我并不会正解于是只好打退火了--其他没啥好讲--只要对每一种颜色开一个vector,存一下所有这个颜色的位置,判定的时候可以去所有的颜色里二分找到前缀和后缀,把和当前点距离小的加入 ...

  7. 【题解】P3162CQOI2012组装

    [题解][CQOI2012]组装 考虑化为代数的形式,序列\(\left[a_i \right]\)表示选取的\(i\)种类仓库的坐标. \(ans=\Sigma(a_i-x)^2,(*)\),展开: ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. [BZOJ2667][cqoi2012]模拟工厂 贪心

    2667: [cqoi2012]模拟工厂 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 367  Solved: 184[Submit][Status] ...

随机推荐

  1. Linux 系统的/var目录

    /var目录主要针对常态性变动的文件,包括缓存(cache).登录档(log file)以及某些软件运作所产生的文件 /var目录下的重要目录 目录 应放置文件内容 /var/cache/ 应用程序本 ...

  2. Ubuntu Linux 14.04 LTS 上安装php7+mysql+nginx

    输入 $ sudo apt-get install -y language-pack-en-base$ sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:o ...

  3. (1)封装 (2)static关键字 (3)继承

    1.封装(重中之重)1.1 基本概念 通常情况下,可以在测试类中给成员变量进行赋值,当给定的数值合法但不合理时,无论是编译还是运行阶段都不会报错或给出提示,此时与现实生活不符. 为了避免上述问题的发生 ...

  4. 利用skipList(跳表)来实现排序(待补充)

    用于排名的数据结构 一般排序为利用堆排序(二叉树)和利用skipList(跳表)的方式 redis中SortedSet利用skipList(跳表)来实现排序,复杂度为O(logn),利用空间换时间,类 ...

  5. MySQL知识总结(二)基本语句总结

    1. 数据库 查看数据库 show databases; 使用数据库 use [数据库名] 如:use mysql 创建数据库 CREATE DATABASE bruce DEFAULT CHARAC ...

  6. 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

    原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...

  7. spring中MessageSource的配置使用方法2--ReloadableResourceBundleMessageSource【转】

    本文转载仅供自己学习收录,不做任何商业用途,如有需要可访问原地址:http://blog.csdn.net/qyf_5445/article/details/8124362 如何在spring mvc ...

  8. JavaScript设计模式—工厂模式

    工厂模式介绍 将new操作符单独进行封装,遇到new时,就要考虑是否该使用工厂模式 举一个生活当中的示例: 你要去购买汉堡,直接点餐,取餐,不会自己动手做,商店要“封装” 做汉堡的工作,做好直接给购买 ...

  9. Installing Oracle Database 12c Release 2(12.2) RAC on RHEL7.3 in Silent Mode

    概要 在RHEL7静默方式安装oracle database 12.2 RAC. 一.环境配置 1. 配置hosts文件 cp /etc/hosts /etc/hosts_$(date +%Y%d%m ...

  10. kong安装

    1 哪些企业在用KONG: Mashapoe Marketplace Buzzlogix Gengo IBM Intel OpenDNS 饿了么 Kong可与两种不同的组件协同工作: Nginx:Ko ...