对于这题本人刚开始的时候的想法是:先把最大两数差的位置找到然后merge计算一个值再与一连串相同的数做merge后计算一个值比较取最大值输出;可提交后发现不对,于是本人就搜了一下正解发现原来这题的正确解题思路是:采用数学中的中位数原理,分别把某数两边相邻且不同的数存入向量容器Vector中然后排序,找到中位数计算一遍,找到计算的最大值,然后把按照输入顺序的值计算出一个总和,然后相减就是其解。
关于中位数原理本人稍微提一下:
求中位数,首先要先进行数据的排序(从小到大),然后计算中位数的序号,分数据为奇数与偶数两种来求。排序时,相同的数字不能省略) [2]
中位数算出来可避免极端数据,代表着数据总体的中等情况。
如果总数个数是奇数的话,按从小到大的顺序,取中间的那个数。
如果总数个数是偶数的话,按从小到大的顺序,取中间那两个数的平均数。
其中中位数的应用就是求与其它元素距离最小之和;本体还涉及到分治思想;好了废话也不说多了就贴一下我的代码吧;
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #define LL __int64 7 using namespace std; 8 const int N = 100000+10; 9 int A[N]; 10 int n,m; 11 int vis[N]; 12 vector<int> v[N]; 13 int abs(int x) 14 { 15 if (x<0) return -x; 16 else return x; 17 } 18 int main() 19 { 20 while (scanf("%d%d",&n,&m)!=EOF) 21 { 22 LL ans=0; 23 memset(vis,0,sizeof vis); 24 for (int i=1;i<=m;i++){ 25 scanf("%d",&A[i]); 26 if (i>1){ 27 if (A[i]!=A[i-1]){ 28 v[A[i]].push_back(A[i-1]); 29 v[A[i-1]].push_back(A[i]); 30 } 31 ans+=(LL)abs(A[i]-A[i-1]); 32 } 33 } 34 LL maxn=0; 35 if (m>1) 36 for (int i=1;i<=m;i++){ 37 if (vis[A[i]]) continue; 38 vis[A[i]]=1; 39 sort(v[A[i]].begin(),v[A[i]].end()); 40 int r=v[A[i]].size(); 41 if (r==0) continue; 42 r/=2; 43 int mid=v[A[i]][r]; 44 LL t1=0; 45 LL t2=0; 46 for (int j=0;j<v[A[i]].size();j++){ 47 t1+=(LL)abs(mid-v[A[i]][j]); 48 } 49 for (int j=0;j<v[A[i]].size();j++){ 50 t2+=(LL)abs(A[i]-v[A[i]][j]); 51 } 52 maxn = max(maxn,t2-t1); 53 } 54 ans -= axn; 55 printf("%I64d ",ans); 56 } 57 return 0; 58 }