博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
笔记 (一道正解思路巧妙的题)
阅读量:4952 次
发布时间:2019-06-11

本文共 2291 字,大约阅读时间需要 7 分钟。

      【问题描述】

给定一个长度为m的序列a,下标编号为1~m。序列的每个元素都是1~n的

整数。定义序列的代价为

  你现在可以选择两个数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。
【数据规模和约定】

  对于30%的数据 n, m <=100

  60%的数据,n,m≤ 2000。
  对于100%的数据,1 ≤ n,m ≤ 100,000。

 

思路:读入数列, 将相邻的数建一条边。

可以用vector动态二维数组来存一个类似于 邻接链表的东西 (只是类似)。

第一维是 第 i 个数,二维是 第 i 个数相连的数。 注意当i=0 和 i=m 时的情况。

预处理完后 。接下来是操作, 把第 i 个数连接的所有数找出中位数,改变中位数即可达到目的。

因为找中位数需要将 i 连接的整个序列遍历一边。十分麻烦。

所以就可以将 第 i 个数所连接数的数列排一遍序 。中间的数即为 中位数 。

用before 存 原来  第 i 个数所连接数的数列 的价值  

after 存 改变后第 i 个数所连接数的数列 的价值,

做before 与 after 的 差即为 要改变的价值 ,把这个价值与上一个价值 取较大值,最终即为要改变的值,

最后 用Sum 存起 所有before 的 和,即为 该序列需求的值。

但是!! 由于 前后两个数加了两遍   

如图,所有的数都被加了两遍 所以答案要 除 2  最后减去 上面求出的要改变的值  即为答案

 

 

 

#include 
#include
#include
#include
d#include
#include
#define Max 1000001using namespace std;int N, M;int number [Max];vector < int > test [Max];long long Answer, Sum;int max (int a, int b){ return a > b ? a : b;}int abs (int a){ return a < 0 ? -a : a;}int main(){ ios :: sync_with_stdio (false); cin >> N >> M; for (int i = 1; i <= M; i++) cin >> number [i]; for (int i = 1; i <= M; i++) { if (i > 1 && number [i - 1] != number [i]) // 防止i等于0 因为下标为0的元素不属于序列 test [number [i - 1]].push_back (number [i]); //建立 类似 于邻接矩阵的东西 ( test [i] 表示 数 i 连接的数有什么) if (i < M && number [i + 1] != number [i]) //防止 超出最大长度 test [number [i + 1]].push_back (number [i]); //同上 } for (int i = 1; i <= N; i++) { if (test [i].size() == 0) //如果第 i 个点没有连接其他点 ,即 没有出现过这个数 ,就跳过 continue; sort (test [i].begin (), test [i].end ()); //把这个数连接 的数 排一遍序 中间的数即为中位数 int y = test [i][test [i].size () >> 1]; //找出中位数 long long before = 0; long long after = 0; for (int j = 0; j < test [i].size (); j++) { before += abs (i - test [i][j]); // 改变之前之前的价值总和 after += abs (y - test [i][j]); // 改变之后的 价值总和 } Answer = max (Answer, before - after); //before - after 是 整个序列改变的值 ,因为要是序列总和尽量小,所以改变的值要尽量大 Sum += before; // Sum 为之前 的 到 第 i 个数的总和 } cout << Sum / 2 - Answer << endl; //因为每个数都加了2遍,所以要除2 后再减去最大的改变值 return 0;}

 

转载于:https://www.cnblogs.com/ZlycerQan/p/6059712.html

你可能感兴趣的文章
install mongodb on macos
查看>>
A-Z
查看>>
iOS 代码混淆的简单使用
查看>>
购物车升级版本
查看>>
移动端遇到的问题
查看>>
ES6中变量的解析赋值的用途
查看>>
load()和get()的区别
查看>>
可遇不可求的Question之反序列化时出现“base-64 字符数组的无效长度”错误提示篇...
查看>>
[计算机网络]简易http server程序
查看>>
学习MVC之租房网站(二)-框架搭建及准备工作
查看>>
旅行 (Standard IO)
查看>>
BigData10 Collections集合工具类 Arrays 数组工具类
查看>>
node + exrepss 实现一个简单的图片爬虫网页
查看>>
【设计模式】六大设计原则总结
查看>>
Elasticsearch入门
查看>>
UEditor常用设置函数记录
查看>>
PHP高效率写法(详解原因)
查看>>
使用HttpUrlConnection连接网络的例程
查看>>
flask-restful在解析的请求一定要传content-type:application/json吗?答:其实不需要!...
查看>>
Dynamic CRM 2015学习笔记(5)CRM 2015 导入 OData Query Designer 解决方案
查看>>