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; }
相关文章推荐
- GitHub学习总结
- SqliteOpenHelper封装——DBManager模板
- 数据链路层和运输层的流量控制及差错控制
- Leetcode[107]-Binary Tree Level Order Traversal II
- 基础篇:8.android编码规范
- 判断当前用户是否为root
- 设计模式之Builder Model(笔记)
- mysql日志
- VC运行时复制函数代码的注意事项
- JSTL标签库的使用和介绍
- sql特殊字符处理
- Linux下GTK实现系统监视器
- sqlserver性能调优方法论与常用工具
- Android ORMLite 框架的入门用法
- 在Windows下使用OpenCL配置
- Ubuntu vi与vim使用
- 利用Hbase的coprocessor实现增量式Apriori算法
- 在不同场合中,让人一听就觉得很地道的英语表达
- UIAutomator 学习版
- 利用异常类记录调用日志