题意:

\(x\)轴上有\(n\)个质量为\(1\)的点,他们的坐标分别为\(x_i\).

质心的坐标为\(\frac{\sum{x_i}} {n}\)

转动惯量为\(\sum{d_i^2}\),其中\(d_i\)为第\(i\)个点到质心的距离.

现在你可以至多移动其中的\(k\)个点,求可能的最小的转动惯量.

分析:

首先可以任意移动其中的\(k\)个点,我们可以选择直接将他们移动到质心的位置使得转动惯量为\(0\).

所以这就相当于删去了\(k\)个点,选剩下的\(n-k\)个点.

还有一个直观的感受是选的点越集中整体的转动惯量越小,所以我们一定要选连续的\(n-k\)个点.

所以就移动长为\(n-k\)的区间,维护一个所有区间的转动惯量的最小值.

在区间移动的过程中,质心也会跟着移动.

在移动的过程中,质心远离了一些点,质心跨过了一些点(即从这些点的左边移动到了右边),质心也靠近了一些点.

所以我们可以将这些点分成左中右三个部分.

  • 对于左边的点来说,转动惯量一直是增大的,而且增量为\((x+ \Delta x)^2-x^2\),化简为\(2x \Delta x+{ \Delta x}^2\).再进行一次求和得到\(2 \sum{x} \Delta x + cnt {\Delta x}^2\),其中\(cnt\)为远离的那些点的个数
  • 对于中间的点,我们就直接计算转动惯量的增量即可.在质心移动的过程中每个点最多被跨过一次,所以这里的复杂度是\(O(n)\)的
  • 对于右边的点来说,转动惯量是一直减小的,减小的量为\(x^2 - (x - \Delta x)^2\),化简为\(2x \Delta x - { \Delta x}^2\).进行求和:\(2 \sum{x} \Delta x - cnt {\Delta x}^2\),其中\(cnt\)为靠近的那些点的个数

上式中的\(\sum{x}\)可以预处理前缀和\(pre\)计算出来.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 50000 + 10;
int n, k;
double x[maxn]; double pre[maxn]; inline double Sum(int i, int j) {
return pre[j] - pre[i - 1];
} int main()
{
//freopen("in.txt", "r", stdin); int T; scanf("%d",&T); while(T--) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++) scanf("%lf", x + i);
sort(x + 1, x + n + 1);
pre[1] = x[1];
for(int i = 2; i <= n; i++) pre[i] = pre[i - 1] + x[i]; double sum = 0, ans;
for(int i = 1; i <= n - k; i++) sum += x[i];
double center = sum / (n - k);
double inertia = 0;
for(int i = 1; i <= n - k; i++) inertia += (x[i] - center) * (x[i] - center);
ans = inertia;
int border = 0;
while(x[border + 1] <= center) border++; for(int s = 2; s <= k + 1; s++) {
int t = s + n - k - 1;
double next_center = center + (x[t] - x[s - 1]) / (n - k);
int next_border = border;
while(next_border < n && x[next_border + 1] <= next_center) next_border++;
double delta = next_center - center; double next_inertia = inertia;
next_inertia -= (x[s-1]-center) * (x[s-1]-center);
next_inertia += (x[t]-center) * (x[t]-center);
int lft = border - s + 1, rgh = t - next_border;
double sigl = center * lft - Sum(s, border);
double sigr = Sum(next_border + 1, t) - center * rgh;
next_inertia += 2 * delta * sigl + lft * delta * delta;
next_inertia -= 2 * delta * sigr - rgh * delta * delta;
for(int i = border + 1; i <= next_border; i++)
next_inertia += (x[i]-next_center)*(x[i]-next_center) - (x[i]-center)*(x[i]-center);
ans = min(ans, next_inertia); center = next_center;
border = next_border;
inertia = next_inertia;
} printf("%.10f\n", ans);
} return 0;
}

LA 7049 Galaxy 枚举的更多相关文章

  1. LA 3695 部分枚举

    运用部分枚举的思想,很明显完全枚举点的思想是不可能的.改为枚举上下边界,当确定右边界j后,对左边界i,可以有点数为on[j]+on[i]+(leftu[j]-leftu[i])+leftd[j]-le ...

  2. LA 3695 Distant Galaxy

    给出n个点的坐标(坐标均为正数),求最多有多少点能同在一个矩形的边界上. 题解里是构造了这样的几个数组,图中表示的很明白了. 首先枚举两条水平线,然后left[i]表示竖线i左边位于水平线上的点,on ...

  3. LA 2402 (枚举) Fishnet

    题意: 正方形四个边界上分别有n个点,将其划分为(n+1)2个四边形,求四边形面积的最大值. 分析: 因为n的规模很小,所以可以二重循环枚举求最大值. 求直线(a, 0) (b, 0) 和直线(0, ...

  4. UVa LA 3695 - Distant Galaxy 前缀和,状态拆分,动态规划 难度: 2

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  5. LA 4253 箭术(二分枚举)

    https://vjudge.net/problem/UVALive-4253 题意: 有n个平行于x轴的线段,每条线段代表一个靶子.判断是否可以站在x轴上[0,W]区间内的某个位置射箭. 思路:二分 ...

  6. LA 4794 状态DP+子集枚举

    状态压缩DP,把切割出的面积做状态压缩,统计出某状态下面积和. 设f(x,y,S)为在状态为S下在矩形x,y是否存在可能划分出S包含的面积.若S0是S的子集,对矩形x,y横切中竖切,对竖切若f(x,k ...

  7. LA 3887 - Slim Span 枚举+MST

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  8. LA 3602 - DNA Consensus String 枚举

    原题地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  9. LA 3602 DNA Consensus String (暴力枚举)

    题意:给定m个长度为n的DNA序列,求一个最短的DNA序列,使得总Hamming距离最小. Hamming距离等于字符不同的位置个数. 析:看到这个题,我的第一感觉是算时间复杂度,好小,没事,完全可以 ...

随机推荐

  1. 在 cell 中获取 textFlied内容的使用

    当您读到这里时,建议先下载demo,不懂再参考博客.在iOS项目开发中,容易遇到各种个人信息填写.比如微信中设置个人信息,等.这种方式是进行控制器跳转,代理或者block传值,这种比较容易,符合常规的 ...

  2. for循环操作DOM缓存节点长度?

    不管是在网上,还是在翻看书籍的时候,都能看到在使用for循环操作DOM节点时要做数节点长度的缓存,以确保性能最优化! 这二种写法格式大致是下面这样的 /*节点集合*/ var domarr=docum ...

  3. mysql-练级查询

    mysql的链接查询中主要有五大类链接查询 1.内连接查询 1.1:等值链接查询:指使用等号"="比较两个表的连接列的值,相当于两表执行笛卡尔后,取两表连结列值相等的记录. SEL ...

  4. UWP开发:存储容器设置&复合设置数据

    有时候为了将应用设置进行分类,需要创建新的容器进行存储应用设置的信息. 1,容器的创建:在一个根容器里嵌套一个新容器 1)首先获取根容器. 2)调用ApplicationDataContainer.C ...

  5. python爬虫之路——正则表达式初识

    正则表达式:是一个特殊的符号系列,检查字符串是否与指定模式匹配. python中的re模块拥有全部的正则表达式功能. 判断字符: 类型: 数目:有无:   个数:单值     区间      离散 判 ...

  6. 【转载】Cesium基础使用介绍

    既然给我发了参与方式,不参加似乎有点不给人面子,反正也没多少人看我的博客,那我就试试吧,也欢迎大家自己参与:2017年度全网原创IT博主评选活动投票:http://www.itbang.me/goVo ...

  7. UVA 11093 Just Finish it up 环形跑道 (贪心)

    有一个环形跑道,上面有n个加油站,到i号加油站可以加pi的油,跑到下一站要花费qi的油,起点任意选,问是否有一个起点可跑完整个跑道. 从i开始跑,如果遇到某个站j不能跑了,那么从i到j之间的站开始跑, ...

  8. UVA 10954 Add All 全部相加 (Huffman编码)

    题意:给你n个数的集合,每次选两个删除,把它们的和放回集合,直到集合的数只剩下一个,每次操作的开销是那两个数的和,求最小开销. Huffman编码.Huffman编码对于着一颗二叉树,这里的数对应着单 ...

  9. jQuery工作中遇到的几个插件

    图片上传插件:uploadify 表单验证插件:formValidator

  10. opencv中mat矩阵如何debug

    mat img 看type:img.type() rows:img.rows cols:img.cols channels:img.channels(),channels()这是一个函数,和上面两个有 ...