题意:

\(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. C#高级语法

    委托 委托就是指针函数,委托的定义与类的属性定义类似都必须在类的方法体进行. 委托的定义: class Program { //定义委托:委托不能在方法体内定义. public delegate st ...

  2. cf519D. A and B and Interesting Substrings(前缀和)

    题意 给出$26$个字母对应的权值和一个字符串 问满足以下条件的子串有多少 首尾字母相同 中间字母权值相加为0 Sol 我们要找到区间满足$sum[i] - sum[j] = 0$ $sum[i] = ...

  3. 1126 数字统计 2010年NOIP全国联赛普及组

    1126 数字统计 2010年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver         题目描述 Description 请统计某个 ...

  4. JavaScript中三种字符串连接方式及其性能比较

    参考地址: https://www.cnblogs.com/programs/p/5554742.html 工作中经常会碰到要把2个或多个字符串连接成一个字符串的问题,在JS中处理这类问题一般有三种方 ...

  5. Lucene-如何编写Lucene程序

    Lucene版本:7.1 使用Lucene的关键点 创建文档(Document),添加文件(Field),保存了原始数据信息: 把文档加入IndexWriter: 使用QueryParser.pars ...

  6. 掌握 Azure 的注册、帐户和订阅管理 Azure 上云须知

    计划使用由世纪互联运营的 Microsoft Azure 的用户,可通过下列流程注册开通并购买所需 Azure 服务:信息获取 > 试用 > 购买 > 账户/订阅管理 > 支付 ...

  7. SpringBoot LogBack文件配置

    <?xml version="1.0" encoding="UTF-8"?> <configuration scan="true&q ...

  8. 安装指定版本的minikube

    Minikube是什么? Kubernetes集群的安装和部署对于很多初学者来说是一道坎.为了方便大家开发和体验Kubernetes,Kubernetes开源社区提供了可以在本地部署的Minikube ...

  9. UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)

    任意线可以贪心移动到两点上.直接枚举O(n^3),会TLE. 所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了.旋转的时候在O(1)时间推出下一种情况,总复杂度为O ...

  10. 变量和数据类型&运算符

    变量和数据类型&运算符 变量 变量的作用:用来存储数据 变量命名的规范:字(字符串)下(_下划线)美($)人(¥) 数 (可以包括数字)骆驼 有意义(可以以字母,下划线,美元符号,人民币符号开 ...