Codeforces433 C Ryouko’s Memory Note

题意:
给你一个长度为 M 的数组ai,每个数都不超过 N 。你可以任意选择一个数x,把与它相同的所有数都替换成 y ,要求使得数组相邻两项的差的绝对值之和最小。
1n,m105,ain

题解:
把所有相同的数的位置记在⼀个链表⾥,枚举改哪个数。那么会更改的差值只会是与这些数相邻的数,因此把这些数拿出来,注意如果两个要改的数相邻,必须忽略它。取⼀个数使得它与⼀些数的距离最⼩,必然是这些数的中位数。

/*
  ID:Agreement
  LANG:C++
*/
// Invincible
#include <bits/stdc++.h>
#define PB push_back
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll; 
vector<int> g[maxn];
int a[maxn];
int main(){
    int N , M , mx = 0 ;
    ll res = 0;
    scanf("%d %d" , &N , &M);
    rep( i , 1 , M ){
        scanf("%d" , &a[i]);
        mx = max( mx , a[i] );
        if( 1 == i ) continue;
        if( a[i] != a[i - 1] ){
            g[a[i - 1]].PB( a[i] );
            g[a[i]].PB( a[i - 1] );
        }
        res += (ll)abs( a[i] - a[i - 1] );
    }
    ll ans = res;
    rep( i , 1 , mx ){
        ll t = res;
        if( 0 == g[i].size() ) continue;
        sort( g[i].begin() , g[i].end() );
        int mid = g[i][g[i].size() / 2];
        rep( j , 0 , g[i].size() - 1 ) t += (ll)( abs(mid - g[i][j]) - abs(i - g[i][j]) );
        ans = min( ans , t );
    }
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值