CodeForces 433C Ryouko's Memory Note (中位数定理)

<题目链接>

题目大意:
给你一堆数字,允许你修改所有相同的数字成为别的数字,不过只能修改一次,问你修改后序列相邻数字的距离和最小是多少。

解题分析:

首先,修改不是任意的,否则那样情况太多了,因为最后只是求序列相邻项差值的绝对值的和,所以我们只需要考虑修改之后能够改变最终答案的情况,因为本题要使差值的绝对值的和最小,所以我们可以利用中位数的性质转化。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N int(1e5+7)
 5 typedef long long ll;
 6 vector<int>G[N];
 7 int n,m,a[N];
 8 
 9 int main(){
10     scanf("%d%d",&n,&m);
11     ll res=0;
12     for(int i=1;i<=m;i++){
13         scanf("%d",&a[i]);
14         if(i>1 && a[i]!=a[i-1]){     //因为没有必要将相同页数的进行merge
15             G[a[i]].push_back(a[i-1]),G[a[i-1]].push_back(a[i]);    //如果第i条信息所在页merge为其它页能够造成最终结果改变,就将它们连边,等一下会进行这些情况的考虑
16             res+=abs(a[i]-a[i-1]);    //得到初始的差值绝对值之和
17         }
18     }
19     ll ans=res;
20     for(int i=1;i<=n;i++){
21         ll sz=G[i].size();
22         if(sz){
23             ll tmp=res;
24             sort(G[i].begin(),G[i].end());
25             int mid=G[i][sz/2];   //第i页改为要必要更改的页码(更改后能对最终的结果造成改变的页码)中的中位数
26             for(int j=0;j<sz;j++)tmp+=abs(mid-G[i][j])-abs(i-G[i][j]);     //根据中位数的性质,mid-G[i][j]之和,必然小于等于i-G[i][j]之和
27             ans=min(ans,tmp);
28         }
29     }
30     printf("%lld\n",ans);
31 }

 

 

2019-02-22

转载于:https://www.cnblogs.com/00isok/p/10417145.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
Codeforces 1806C题目链接:https://codeforces.com/problemset/problem/1806/C 题目描述: 给定一个长度为 $n$ 的整数序列 $a_1,a_2,\dots,a_n$,你可以进行任意多次操作,每次操作可以选择一个区间 $[l,r]$,将区间内的所有数加上 $1$ 或者减去 $1$。你的目标是使得序列中的所有数都相等,求最小的操作次数。 解题思路: 首先考虑对于一个数来说,如何将它变成序列中的所有数。由于每次操作可以将一个区间内的数全部加上或减去 $1$,所以我们可以将该数变成序列中的中位数中位数是序列中所有数排完序后处在中间的数,如果序列长度为偶数,则中位数是中间两个数的平均数。 接下来考虑对于整个序列来说,如何将所有数变成相等的数。我们可以先将所有数变成中位数,然后计算每个数与中位数的差值之和,这个值就是最小的操作次数。 最后考虑如何将一个数变成中位数。设序列长度为 $n$,$x$ 为中位数,则有以下两种情况: - 当 $n$ 为奇数时,$x=a_{\lfloor\frac{n+1}{2}\rfloor}$。 - 当 $n$ 为偶数时,$x=\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$。 对于第一种情况,我们可以将序列中所有数先减去 $a_{\lfloor\frac{n+1}{2}\rfloor}$,然后再进行操作。 对于第二种情况,我们可以将序列中所有数先减去 $\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$,然后再进行操作。注意,当 $n=2$ 时,$\frac{n}{2}=1$,需要特判。 代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值