您的位置:首页 > 其它

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处取点各个点距离最小。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: