您的位置:首页 > 其它

Codeforces Round #248 (Div. 2) C - Ryouko's Memory Note

2015-06-13 11:09 501 查看

题意

一本书有n页。下面要找m个知识点,分别在s[1] s[2]….s[m]页上。

现在有一个机会,可以把某一页的知识点全部移到另一页上。求最少的翻页次数。

如s[1] s[2] …. s[m]的翻页次数就是|s[1]-s[2]|+|s[2]-s[3]|+…+|s[m-1]-s[m]|

思路

记录每个页码在序列中前后出现的页码(如1 2 3 2 4 则2前后出现过1 3 3 4)(注意如果相邻的页码相同则不用管它) 取它们的中位数,这时一定会有移动这个页码的最优解。把所有页码遍历一遍,取整体最优解即可。

代码

[code]#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 100010;
const ll INF = 1e10L;
int s[maxn];
vector<int> ss[maxn];
ll close[maxn];
ll closee[maxn];
ll sum;
ll ans;
int ma;
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= m ; i ++) {
        scanf("%d",&s[i]);
        ma = max(ma,s[i]);
        if(i != 1) {
            sum += abs(s[i]-s[i-1]);
            if(s[i] == s[i-1]) continue;
            ss[s[i]].push_back(s[i-1]);
            ss[s[i-1]].push_back(s[i]);
            close[s[i]] += abs(s[i]-s[i-1]);
            close[s[i-1]] += abs(s[i]-s[i-1]);
        }
    }
    ans = sum;
    for(int i = 1 ; i <= ma ; i ++) {
        if(!ss[i].size()) continue;
        sort(ss[i].begin(),ss[i].end());
        int mid = ss[i].size()/2;
        for(int j = 0 ; j < ss[i].size() ; j ++) {
            closee[i] += abs(ss[i][j]-ss[i][mid]);
        }
        ans = min(ans,sum-close[i]+closee[i]);
    }
    cout << ans << endl;
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: