Codeforces Round #274(Div2) B. Towers 贪心
2015-07-15 14:04
471 查看
解法一:复杂度为O(nk)
每次从最大值向最小值移动1个
代码如下:
本题中n范围较小,所以O(nk)的复杂度没问题
解法二:复杂度为O(nlogn)
思路:在有序的数组中将最大值向最小值移动1,可以保证数组仍然有序。
首先排一次序,记录每个高度的tower个数。每次从数组的末端区间(最大值处)向前端区间(最小值处)移动1。目的是让max_val减小,min_val增大。整个过程中记录下最大值的起点upper和最小值的起点lower,根据最大值的个数more和最小值的个数less的大小关系讨论。
①当more > less时,说明最大值的tower数目比最小值的tower数目多,则最小值的tower全部可以增加一个高度,新的高度仍为最小值,则lower = 0,min_val增加1;此时只有less个最大tower的高度减小了1,下次应从第upper - less个tower开始减小高度
②当more < less时,说明最小值的tower数目较多,则最大值的tower全部可以减小一个高度,新的高度仍为最大值,则upper = n - 1,max_val减小1;此时只有more个最小tower的高度增加了1,下次应从第lower + more个tower开始增加高度
③当more = less时,说明每一个最大值的tower都有一个最小值的tower可以移动过去,从而max_val和min_val向理想的方向靠近,lower和upper都回到数组的首尾两端
代码如下:
每次从最大值向最小值移动1个
代码如下:
#include <cstdio> using namespace std; #define N 1005 int a[105], ans [2]; int main(){ int n, k, ops = 0, max_val, min_val; scanf("%d %d", &n, &k); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); while(ops <= k){ max_val = 0, min_val = 10005; int max_idx, min_idx; for(int i = 1; i <= n; i ++){ if(max_val < a[i]) max_val = a[i], max_idx = i; if(min_val > a[i]) min_val = a[i], min_idx = i; } if(max_val - min_val < 2 || ops == k) break; ans[ops][0] = max_idx, ans[ops][1] = min_idx; a[max_idx] --, a[min_idx] ++; ops ++; } printf("%d %d\n", max_val - min_val, ops); for(int i = 0; i < ops; i ++) printf("%d %d\n", ans[i][0], ans[i][1]); return 0; }
本题中n范围较小,所以O(nk)的复杂度没问题
解法二:复杂度为O(nlogn)
思路:在有序的数组中将最大值向最小值移动1,可以保证数组仍然有序。
首先排一次序,记录每个高度的tower个数。每次从数组的末端区间(最大值处)向前端区间(最小值处)移动1。目的是让max_val减小,min_val增大。整个过程中记录下最大值的起点upper和最小值的起点lower,根据最大值的个数more和最小值的个数less的大小关系讨论。
①当more > less时,说明最大值的tower数目比最小值的tower数目多,则最小值的tower全部可以增加一个高度,新的高度仍为最小值,则lower = 0,min_val增加1;此时只有less个最大tower的高度减小了1,下次应从第upper - less个tower开始减小高度
②当more < less时,说明最小值的tower数目较多,则最大值的tower全部可以减小一个高度,新的高度仍为最大值,则upper = n - 1,max_val减小1;此时只有more个最小tower的高度增加了1,下次应从第lower + more个tower开始增加高度
③当more = less时,说明每一个最大值的tower都有一个最小值的tower可以移动过去,从而max_val和min_val向理想的方向靠近,lower和upper都回到数组的首尾两端
代码如下:
#include <cstdio> #include <algorithm> using namespace std; #define N 10005 struct Node{ int val, idx; friend bool operator< (const Node& a, const Node& b){ return a.val < b.val; } }towers[105]; int cnt , ans[1005][2], ops = 0, k; void fill(int fill_cnt, int upper, int lower){ //从最大值向最小值移动1 int j = 0; while(j < fill_cnt && ops < k){ ans[ops][0] = towers[upper - j].idx, ans[ops][1] = towers[lower + j].idx; ops ++, j ++; } } int main(){ int n; scanf("%d %d", &n, &k); for(int i = 0; i < n; ++i){ int x; scanf("%d", &x), cnt[x] ++; towers[i].val = x, towers[i].idx = i + 1; } sort(towers, towers + n); int max_val = towers[n - 1].val, min_val = towers[0].val; int upper = n - 1, lower = 0; while(ops < k && max_val - min_val > 1){ //最大值和最小值隔1时,最优解已无法减小 int more = cnt[max_val], less = cnt[min_val]; if(more > less && ops + less <= k){ //最小的tower都增加了1个高度 fill(less, upper, lower); cnt[++min_val] += less, cnt[max_val] -= less, cnt[max_val - 1] += less; upper -= less, lower = 0; } else if(more < less && ops + more <= k){ //最高的tower都减小了1个高度 fill(more, upper, lower); cnt[--max_val] += more, cnt[min_val] -= more, cnt[min_val + 1] += more; lower += more, upper = n - 1; } else{ if(ops + more <= k) cnt[--max_val] += more, cnt[++min_val] += less; fill(more, upper, lower); upper = n - 1, lower = 0; } } printf("%d %d\n", max_val - min_val, ops); for(int i = 0; i < ops; i ++){ printf("%d %d\n", ans[i][0], ans[i][1]); } return 0; }
相关文章推荐
- Android SnackBar
- Linux strace命令
- WebLogic之Session
- asp.net如何读写xml文件
- c# 对一下XML文档进行添加删改的实例
- SDWebImage的简单使用
- iOS开发——UI基础-自定义构造方法,layoutSubviews,Xib文件,利用Xib自定义View
- ubuntu/linux mint 创建proc文件的三种方法(两)
- 单例设计模式
- LeetCode - Largest Number (sort的cmp的写法)
- envi 监督分类超详细过程
- Chapter 5. Forms
- 项目练习:自己写一个CheckBoxList,RadioButtonList控件
- Delphi LoadUserProfile
- 错误:Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
- Leetcode_100 Same Tree
- Web应用遇到问题记录
- java.lang.IllegalStateException: cannot resize buffer, 305 bytes have been written (Servlet 2.3, sec
- DATAGRID固定表头【转】
- [蜂鸣器不简单]单片机中蜂鸣器的多种运用(长响,短响,多次响)