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

posted @ 2019-02-22 11:06  悠悠呦~  阅读(323)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end