Codeforces RoundC. Ryouko's Memory Note
2016-04-16 16:18
281 查看
题目意思:给一组序列,找到一个点,变成另外一个点,使这个序列左右之间的绝对值之和最小。
列出一个vector数组,每个保存该点相邻的数(与本点相同的不保存),然后查找每个点,令该点与vector内相邻的数的中位数相交换,得到最小的和。
与中位数交换的原因:假设有十个点,我们取第7个点为当前点,现在换到第6个点,第7点与第6点距离为d,那么1-6点距离和减少6d,7-10点距离和增加4d,总共的距离和减少了2d,以此类推,即处在中间位置的点与各个点的距离和最小。若序列为偶数1,2,……n,n+1,……,2n,那么在n~n+1之间任意取点与各个点距离最小,若序列为奇数,1,2,……,n,则在n/2+1处取点各个点距离最小。
列出一个vector数组,每个保存该点相邻的数(与本点相同的不保存),然后查找每个点,令该点与vector内相邻的数的中位数相交换,得到最小的和。
与中位数交换的原因:假设有十个点,我们取第7个点为当前点,现在换到第6个点,第7点与第6点距离为d,那么1-6点距离和减少6d,7-10点距离和增加4d,总共的距离和减少了2d,以此类推,即处在中间位置的点与各个点的距离和最小。若序列为偶数1,2,……n,n+1,……,2n,那么在n~n+1之间任意取点与各个点距离最小,若序列为奇数,1,2,……,n,则在n/2+1处取点各个点距离最小。
#include<iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<vector> #include<list> #include<algorithm> using namespace std; int main(){ int n,m; vector<long long > a[100005]; scanf("%d%d",&n,&m); long long num[100005]; int maxn = 0; for(int i=0;i<m;i++){ scanf("%I64d",&num[i]); if(maxn<num[i]){ maxn = num[i]; } } long long sum = 0; for(int i=1;i<m;i++){ if(num[i-1]!=num[i]){ sum += abs(num[i-1]-num[i]); a[num[i-1]].push_back(num[i]); a[num[i]].push_back(num[i-1]); } } long long result = sum; for(int i=1;i<=maxn;i++){ long long temp = sum; int l = a[i].size(); if(l!=0){ sort(a[i].begin(),a[i].end()); //中位数正确 int mid = a[i][l/2]; /*int mid = 0; //平均数错误 for(int k = 0;k<l;k++){ mid += a[i][k]; } mid/=l; */ for(int j=0;j<l;j++){ temp = temp + abs(mid-a[i][j]) - abs(i-a[i][j]); } } result = min(result,temp); } printf("%I64d\n",result); return 0; }
相关文章推荐
- 回文
- 深入Java集合学习系列:HashMap的实现原理
- R语言学习
- 界面编程与视图(view)组件——三种UI界面开发方式
- python中socket【TCP】基本编程知识
- __attribute__ ((default)) 和 __attribute__ ((hidden))
- 跳转到短信界面
- Laravel Repository 模式
- Android设计模式之建造者模式(Builder Pattern)
- mybatis缓存的使用及理解
- C/C++编程规范
- c#之线性表(顺序表)实现(第四季)
- Logistic回归
- 修改PE加载dll
- 核桃数量
- Swift-AES之加密解密
- 模板--判断两线段是否相交
- GRAY
- 分析C语言的声明的优先级
- SqlDataAdapter有关InsertCommand,UpdateCommand,DeleteCommand 实例