[总结]中位数及带权中位数问题

目录

  • 一、中位数问题

    • 1. 问题模型
    • 2. 结论
    • 3. 推导
    • 4. 例题
  • 二、带权中位数问题
    • 1. 问题模型
    • 2. 结论
    • 3. 推导
    • 4. 例题

一、中位数问题

1. 问题模型

数轴\(x\)上有\(n\)个点,现在给出这\(n\)个点的坐标\(a[i](i\in [1,n])\),让你选择一个点\(k(k\in [1,n])\),使得每个点到点\(k\)的距离之和最小。

2. 结论

点\(k\)为序列的中位数时最优:
若n为奇数,点\(k\)位于a[(n+1)/2]处最优;若n为偶数,点\(k\)位于\(a[n/2]\)或\(a[n/2+1]\)均为

3. 推导


首先将\(a[1]\)~\(a[n]\)排序,假设点\(p\)选在坐标\(q\)处,点\(p\)左侧有\(l\)个点,点\(p\)右侧有\(r\)个点,此时分为两种情况:
\(l\lt r\),若点\(p\)向右移动单位距离,则距离之和减小\((r-l)\)。
\(r\lt l\),若点\(p\)向左移动单位距离,则距离之和减小\((l-r)\)。

因此保证点p的左侧节点和右侧节点数量尽量相等时(即\(l=r\)),距离之和最优。

该结论同样适用于求出最优点\(k\),当点\(k\)的左右两侧节点数相等时为最优解,此时\(k\)就是序列的中位数。此时无论左移或右移点\(k\)都会使结果更差。

4. 例题

[CH0501]货仓选址

描述
在一条数轴上有N家商店,它们的坐标分别为 A[1]~A[N]。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

输入格式
第一行一个整数N,第二行N个整数A[1]~A[N]。
输出格式
一个整数,表示距离之和的最小值。

样例输入
4
6 2 9 1
样例输出
12
数据范围与约定
对于100%的数据: N<=100000, A[i]<=1000000

显然,将货仓建于中位数处最优。
Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,pos,a[100010];ll ans=0;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    if(n&1) pos=(n+1)>>1;
    else pos=n>>1;
    for(int i=1;i<=n;i++)
        ans+=abs(a[pos]-a[i]);
    printf("%d",ans);
    return 0;
}

二、带权中位数问题

1. 问题模型

数轴\(x\)上有\(n\)个点,现在给出这\(n\)个点的坐标\(a[i](i\in [1,n])\)以及这\(n\)个点的点权\(num[i]\),让你选择一个点\(k(k\in [1,n])\),使得每个点到点\(k\)的距离与点权的乘积之和最小。

2. 结论

满足\(\sum_{i=1}^{k} num[i]\geq tot/2\)时(\(tot\)为所有点权之和)的最小点\(k\)为最优点。

3. 推导

可以把每个节点\(i\)由原来只有一个节点看做有\(num[i]\)个点同时位于坐标\(i\)上,此时我们知道当点\(k\)位于\(tot/2\)的坐标上最优。

4. 例题

抗震救灾

问题描述
这场灾难发生后,国家决定设立研究所研究灾后重建工作,由全国各地派技术人员来参加。因为每个地区所派的技术人员数目不
同,出于节约经费的问题,所以目前还没有决定到底有在哪个地区设置研究所进行研究。假设所有地区都在一条直线上,现在
只知道每个地区与汶川的距离和该地派出技术人员的数目(假设汶川在最左端)。请你编程帮助他们确定在哪个地区建立研究
所可以使所有技术人员集中到该地区的费用总和最小。

输入格式
输入文件每一行描述一个地区的信息(地区数<=5000)。 对于每一行,首先是该地区派出的技术人员数目,紧跟着是这个地区相对于汶川的距离,最后是该地区的名称。(技术人员数<=100,地区的相对距离<=10^31,地区名称长度<=20,数据保证有唯一的解);
输出格式
输出文件只需一行,即研究所设定的地区名称。

Sample Input1
7 9289 shengyan
5 8523 beijing
3 5184 guilin
8 2213 chongqing
10 0 wuhan
Sample Output1
chongqing

Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n=1;
ll tot,sum=0;
struct node{
    ll num,dis;
    char name[50];
    bool operator < (const node &other) const{
        return dis<other.dis;
    }
}p[5050];
int main()
{
    while(scanf("%lld%lld%s",&p[n].num,&p[n].dis,p[n].name)!=EOF) tot+=p[n].num,n++;
    n--;
    sort(p+1,p+n+1);
    for(int i=1;i<=n;i++){
        sum+=p[i].num;
        if(sum>=tot/2){
            printf("%s\n",p[i].name);
            return 0;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cyanigence-oi/p/11828135.html

时间: 2024-10-16 03:44:59

[总结]中位数及带权中位数问题的相关文章

中位数及带权中位数题集

codevs 3625 1 #include <bits/stdc++.h> 2 using namespace std; 3 int x[11111], y[11111]; 4 int main() 5 { 6 int n; scanf("%d", &n); 7 for(int i = 1; i <= n; i++) scanf("%d %d", &x[i], &y[i]); 8 ///先处理y 9 sort(y + 1,

[POJ 1723]SOLDIERS(带权中位数问题)

题目链接:http://poj.org/problem?id=1723 最近因为在为NOIP 2014复习,一直没写啥题解... 这个题目的意思是给你n个士兵在棋盘里的坐标,要你将他们排成连续的一行(即与x轴平行),问你最少要将这些士兵移动多少步. 思路:设最终连续的一行的开头坐标为(linex,liney),终点坐标为(linex+n-1,liney) 将x坐标和y坐标分开讨论. y坐标上,要让士兵移动步数最少,则liney=士兵们的y坐标的中位数 x坐标上士兵的移动步数=|x1-linex|

poj 1723 SOLDIERS 带权中位数

题目 http://poj.org/problem?id=1723 题解 带权中位数类型的题目~ 可以先考虑降维,最后集合的y坐标,明显是y坐标的中位数的位置,容易求出y方向的贡献res_y.比较麻烦的是在x坐标上最后是要列成一排,而不是单独的一个点,我们可以假设最后集合的最左边的点是x,采用贪心的策略列出公式:res_x=sum(abs(xi-x-i))(i belongs to [0,n-1]).令zi=xi-i,就转化为res_x=sum(abs(zi-x)),这相当于求zi数列的中位数(

带权中位数

话说在3085年,外星人打算来入侵地球,这个消息被我国的情报部门秘密截获,于是便打算联系世界各个国家,一 起研究商量对策.由于每个国家所需派的技术员人数不同,所以目前无法决定到底要在哪个国家设置个研究所进行 研究,幸运的是所有国家都在一条直线上,现在知道每个国家与我国的距离和该国的研究员人数.请你为他们决定 一下到底在那个国家建立研究所可以使所有研究员集中到该国的费用最小. Input 输入文件每一行描述一个国家的信息. 首先是该国派出的技术员人数,紧跟着的是这个城市相对于我国的距离,最后是国家

数学 + 带权中位数 - SGU 114 Telecasting station

Telecasting station Problem's Link Mean: 百慕大的每一座城市都坐落在一维直线上,这个国家的政府决定建造一个新的广播电视台. 经过了许多次试验后,百慕大的科学家们提出了一个结论:在每座城市的不满意度等于这座城市的市民数与这座城市与广播电视台的距离的乘积. 你需要找到这个一维直线上的一点来建造广播电视台,使得所有城市的不满意度的和最小. analyse: 个人觉得应该是加权平均数,然而却是求中位数. 可以这样想:随便挑一个点作为station,左右移动一下看看

Putting Boxes Together CodeForces - 1030F (带权中位数)

#include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #include <bitset> #define REP(i,a

Java数据结构——带权图

带权图的最小生成树——Prim算法和Kruskal算法 带权图的最短路径算法——Dijkstra算法 package graph; // path.java // demonstrates shortest path with weighted, directed graphs 带权图的最短路径算法 // to run this program: C>java PathApp ////////////////////////////////////////////////////////////

并查集模板 &amp;&amp; 带权并查集模板

不带权: 1 int f[50050]; 2 void init(void) 3 { 4 for(int i=1;i<=n;i++) 5 f[i]=i; 6 } 7 int fd(int x) 8 { 9 return f[x]==x?x:fd[x]=fd(f[x]); 10 } 11 int uion(int x,int y) 12 { 13 int fa=fd(x),fb=fd(y); 14 if(fa!=fb)f[fa]=fb; 15 } 带权: 1 int f[K],rl[K]; 2 3

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中