• 【考前模拟】笔记 (不知道神魔算法)


    笔记
    【问题描述】
    给定一个长度为m的序列a,下标编号为1~m。序列的每个元素都是1~n的
    整数。定义序列的代价为

    m-1
    ∑|a[i+1]-a[i]|
    i=1
    你现在可以选择两个数x和y,并将序列a中所有的x改成y。x可以与y相等。
    请求出序列最小可能的代价。
    【输入格式】
    输入第一行包含两个整数n和m。第二行包含m个空格分隔的整数,代表序
    列a。
    【输出格式】
    输出一行,包含一个整数,代表序列最小的代价。
    【样例输入 1】
    4 6
    1 2 3 4 3 2
    【样例输出 1】
    3
    【样例输入 2】
    10 5
    9 4 3 8 8
    【样例输出 1】
    6
    【样例解释】
    样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。
    测试题 #4 笔记
    第 3 页 共 6 页
    【数据规模和约定】
    31。
    60%的数据,?,? ≤ 2000。
    对于100%的数据,1 ≤ ?,? ≤ 100,000。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <ios>
    #include <vector>
    using namespace std;
    typedef long long ll;//typedef类性定义,目的是为了使源代码更易于阅读和理解; 
    const int N=(int)1e5;
    int n, m, a[N+1];
    vector<int>b[N+1];//定义二维动态数组b; 
    int main(/*int argc, char *argv[]*/){
        //freopen("note.in", "r", stdin);
        //freopen("note.out", "w", stdout);
        ios::sync_with_stdio(false);/*读入优化,使 cin快于scanf;*/ 
        cin>>n>>m;
        for(int i=1;i<=m;++i) cin>>a[i];
        for(int i=1;i<=m;++i){
            if(i>1&&a[i-1]!=a[i]) b[a[i-1]].push_back(a[i]);
            if(i<m&&a[i+1]!=a[i]) b[a[i+1]].push_back(a[i]);
        }/*把与a[i]相邻的点记录在以a[i]为标志的数组中 */
        ll ans=0LL, sum=0LL;/*定义ans,sum是long long类型的;*/  
        for(int i=1;i<=n;++i){/*枚举从1到n所有的点;*/ 
            if(!b[i].size()) 
                continue;/*如果该点没有相邻的点,
        那么该点不在数组a中,继续下个循环*/ 
            sort(b[i].begin(),b[i].end());/* 对于他相邻得点进行排序*/ 
            int y=b[i][b[i].size()>>1];/*找出其中的中位数;*/ 
            ll before=0LL,after=0LL;/*定义before,after是long long类型的,
        before用于记录修改前的该点与其相邻点的和值,
        after用于记录该点修改后与其相邻点的和值;*/ 
            for(int j=0;j<b[i].size();++j){
                before+=abs(i-b[i][j]);
                after+=abs(y-b[i][j]);
            }/*计算和值*/ 
            ans=max(ans,before-after/*这个用于记录该点的变化值*/);/*用ans记录所能减小的最大值*/ 
            sum+=before;/*sum用于存储总和,因为最每个点都加了两遍,所以下面输出时,先除2,再减ans;
            举个例子:在1 2 3 4 3 2 这个样例中,对于2加了一遍3与2的差,但对于又3加了一遍3与2的差 
            这就相当于加了2个3与2的差,其余都是这样,那最后计算出的ans是10而不是5,所以除2*/ 
        }
        cout<<sum/2-ans<<endl;
        //fclose(stdin);
        //fclose(stdout);
        return 0;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    【Web-Components】document.registerElement
    Date
    类型转换
    【Web-Components】HTML imports
    【Web-Components】
    【Web-Components】Shadow Dom
    【Mobile】
    数据库读写分离
    HDU——T 1711 Number Sequence
    洛谷——P2957 [USACO09OCT]谷仓里的回声Barn Echoes
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/6058945.html
Copyright © 2020-2023  润新知