cf 433 C(思维题)

45 篇文章 0 订阅

     

链接:http://codeforces.com/problemset/problem/433/C

   

        思路:可以先计算总的消耗,接着计算将某一类型的所有数字更换成相邻的数字之后所降低消耗的最大值。。

可以枚举每一个数换成相邻的数字之后减低的消耗,正常枚举肯定会超时。所以需要我们先求出每一个相邻数字的前缀和,接着枚举一个可以用o(1)的时间算出降低的消耗,具体看代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long

vector<ll>v[100005];
map<int,int>ma;
map<int,int>::iterator it;
int a[100005];
ll rem[100005];
int main()
{

    int n,m;
    ll res=0,temp=0;
    scanf("%d%d",&n,&m);
    for(int i=0;i<100005;i++)
        v[i].clear();
    ma.clear();
    for(int i=1;i<=m;i++)
    {
        scanf("%d",a+i);
        if(i!=1)
        res+=fabs(a[i]-a[i-1]);  //先求出总的消耗
        ma[a[i]]++;
    }
    for(int i=1;i<=m;i++)  //相邻的数字压入邻接表 相同数字就没有必要了
    {
        if(i!=1&&a[i-1]!=a[i])v[a[i]].push_back(a[i-1]);
        if(i!=m&&a[i+1]!=a[i])v[a[i]].push_back(a[i+1]);
    }
    ll r=0;
    for(it=ma.begin();it!=ma.end();it++)
    {
        int i=it->first;
        int t=v[i].size();
        if(t==0)continue;
        sort(v[i].begin(),v[i].end()); //求前缀和前先排序
        rem[0]=v[i][0];
        temp=fabs(v[i][0]-i);
        for(int k=1;k<t;k++)
        {
            rem[k]=rem[k-1]+v[i][k];
            temp+=fabs(v[i][k]-i);
        }
        ll tem=0,ans=0;
        for(int k=0;k<t;k++)  //接着枚举每一个相邻数字 
        {
            tem=rem[t-1]-rem[k]-(ll)(v[i][k]*(t-k-1))+(ll)(v[i][k]*(k+1))-rem[k];
            if(temp-tem>ans)
                ans=temp-tem;
        }
        r=max(r,ans);
    }
    printf("%lld\n",res-r);
    return 0;
}


  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值