(点击此处查看原题)

题意分析

给出n个数,a1,a2...an,现在可以进行最多k次操作,每次操纵可以使得任意一个数自增或者自减,问经过最多k次操作后,n个数中的最大值-最小值最小为多少?

解题思路

一开始,看到k最大可达1e14,就知道这个肯定不能暴力求解...但是我们可以通过优化暴力的方法来解题

注意到,我们只需要考虑最大值和最小值之差,因此我们要么使得最小值增加,要么使得最大值减少,但是每个数一个个地增加太慢,所以我们记录下每个数的数量和值,这样就可以一次性将最小值或者最小值进行增减了

然后,要是我们让当前最大值和最小值仅仅自增或者自减的话,显然很浪费时间,因为会进行很多的重复操作(例:在当前最小值自增到次小值的过程中,会不断地重复同样的计算)

所以我们通过最小值min的和次小值min_s进行判断,如果当前剩余可操作次数k'可以使得最小值增加到次小值的值,即 k' >= (min_s - min) * num[min],那么我们令 k' -= (min_s - min) * num[min],对于最大值同理

以上说明了如何快速地对数进行操作,接下来就需要考虑每次选择最大值还是最小值进行操作了

很简单的道理,选择最小值和最大值中数量num最小者进行上述所示的操作,可以用最小的操作次数使得最大者和最小值的差值最小

最后,总结算法:

【1】将n个数转化位结构体变量number,number.val表示这个数的值,number.num表示值为number.val的数的个数

【2】对number按照number.val的值升序排序

【3】每次选出number中最大值number[l] 和 最小值 numer[r]

  如果number[l].num < number[r],num ,执行步骤【4】

  否则,执行步骤【5】

【4】判断当前数number[l].val是否可以增加到次小值number[l+1].val

    如果 k >= (number[l+1].val - number[l].val)*number[l].num    

      k -= (number[l+1].val - number[l].val)*number[l].num;
      number[l+1].num += number[l].num;
      l++;

    否则,说明无法通过增加number[l].val 达到次小值number[l+1].val,所以让number[l].val尽量大,用尽操作次数后输出答案并结束程序

      ll left = number[l].val + k / number[l].num;
      printf("%lld\n",number[r].val - left);
      return 0;

  【5】判断当前数number[r].val是否可以减少到次大值number[r-1].val

    如果 k >= (number[r].val - number[r-1].val)*number[l].num    

      k -=  (number[r].val - number[r-1].val)*number[l].num;
      number[r-1].num += number[r].num;
      r--; 

    否则,说明无法通过减少number[r].val 达到次大值number[r-1].val,所以让number[r].val尽量小,用尽操作次数后输出答案并结束程序

      ll right = number[r].val - k / number[r].num;
      printf("%lld\n",right - number[l].val);
      return 0;

  【6】如果l < r ,回到步骤【3】

    否则,说明 l == r ,输出0,表示最终使得最大值和最小值相等,答案即为0

代码区

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const ll inf = 1e18 + ;
const int Max = 1e5 + ; struct Number
{
ll val, num;
} number[Max]; int n, tot;
int a[Max];
ll k; int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
scanf("%d%lld", &n, &k);
for (int i = ; i <= n; i++)
scanf("%d", a + i);
sort(a + , a + + n);
tot = ;
for (int i = ; i <= n; i++)
{
if (a[i] == a[i - ])
number[tot].num++;
else
number[++tot].num = , number[tot].val = a[i];
}
int l = , r = tot;
while (l < r)
{
if (number[l].num < number[r].num)
{
ll dis = (number[l+].val - number[l].val)*number[l].num;
if(k >= dis)
{
k -= dis;
number[l+].num += number[l].num;
l++;
}
else
{
ll left = number[l].val + k / number[l].num;
printf("%lld\n",number[r].val - left);
return ;
}
}
else
{
ll dis = (number[r].val - number[r-].val)*number[r].num;
if(k >= dis)
{
k -= dis;
number[r-].num += number[r].num;
r--;
}
else
{
ll right = number[r].val - k / number[r].num;
printf("%lld\n",right - number[l].val);
return ;
}
}
}
printf("0\n");
return ;
}

codeforces 1244E Minimizing Difference (贪心)的更多相关文章

  1. Codeforces 1244E. Minimizing Difference

    传送门 首先减的顺序是无关紧要的,那么有一个显然的贪心 每次减都减最大或者最小的,因为如果不这样操作,最大的差值不会变小 那么直接把序列排序一下然后模拟一下操作过程即可,别一次只减 $1$ 就好 #i ...

  2. codeforces 704B - Ant Man 贪心

    codeforces 704B - Ant Man 贪心 题意:n个点,每个点有5个值,每次从一个点跳到另一个点,向左跳:abs(b.x-a.x)+a.ll+b.rr 向右跳:abs(b.x-a.x) ...

  3. Codeforces 903D Almost Difference

    Codeforces 903D Almost Difference time limit per test 2 seconds memory limit per test 256 megabytes ...

  4. CodeForces - 50A Domino piling (贪心+递归)

    CodeForces - 50A Domino piling (贪心+递归) 题意分析 奇数*偶数=偶数,如果两个都为奇数,最小的奇数-1递归求解,知道两个数都为1,返回0. 代码 #include ...

  5. Codeforces 161 B. Discounts (贪心)

    题目链接:http://codeforces.com/contest/161/problem/B 题意: 有n个商品和k辆购物车,给出每个商品的价钱c和类别t(1表示凳子,2表示铅笔),如果一辆购物车 ...

  6. CodeForces 176A Trading Business 贪心

    Trading Business 题目连接: http://codeforces.com/problemset/problem/176/A Description To get money for a ...

  7. Codeforces Gym 100803C Shopping 贪心

    Shopping 题目连接: http://codeforces.com/gym/100803/attachments Description Your friend will enjoy shopp ...

  8. Codeforces 486C Palindrome Transformation(贪心)

    题目链接:Codeforces 486C Palindrome Transformation 题目大意:给定一个字符串,长度N.指针位置P,问说最少花多少步将字符串变成回文串. 解题思路:事实上仅仅要 ...

  9. Codeforces 1154D - Walking Robot - [贪心]

    题目链接:https://codeforces.com/contest/1154/problem/D 题解: 贪心思路,没有太阳的时候,优先用可充电电池走,万不得已才用普通电池走.有太阳的时候,如果可 ...

随机推荐

  1. 1628:X-factor Chain

    1628:X-factor Chain 时间限制: 1000 ms         内存限制: 524288 KB提交数: 122     通过数: 68 [题目描述] 原题来自 POJ 3421 输 ...

  2. [python]字典的直接赋值、浅拷贝和深拷贝解析

    1.赋值引用 b = a: a 和 b 都指向同一个对象. 2.浅拷贝 b = a.copy():  a 和 b父对象是一个独立的对象,但他们的子对象还是指向统一对象(是引用). 3.深拷贝 b = ...

  3. IntelliJ IDEA 设置忽略SVN文件和文件夹

       IntelliJ IDEA 在提交文件至SVN时,可以设置忽略某些文件和文件夹,以免误提交不需要提交的文件.最后,插个题外话,介绍一下如何设置代码默认折叠或者展开.下面使用IntelliJ ID ...

  4. Flutter移动电商实战 --(28)列表页_商品列表后台接口调试

    主要调试商品列表页的接口 这个接口是最难的因为有大类.小类还有上拉加载 先配置接口 config/service_url.dart //const serviceUrl='http://test.ba ...

  5. Java同步数据结构之ConcurrentLinkedDeque

    前言 由于LinkedBlockingDeque作为双端队列的实现,采用了单锁的保守策略使其不利于多线程并发情况下的使用,故ConcurrentLinkedDeque应运而生,它是一种基于链表的无界的 ...

  6. Android 屏幕适配之dimens适配

    Android 屏幕适配之dimens适配     转  https://blog.csdn.net/github_2011/article/details/72636851 在过去多个项目中一直使用 ...

  7. Qt编写自定义控件28-颜色滑块面板

    一.前言 相比于上一个颜色按钮面板,此控件就要难很多,颜色值有三种表示形式,除了程序员最常用的RGB以外,还有HSB和CMY方式. RGB色彩模式是工业界的一种颜色标准,是通过对红(R).绿(G).蓝 ...

  8. [转]c3p0学习-JdbcUtil工具类

    原文:https://www.cnblogs.com/jonny-xu/p/6374163.html 一.需要jar包: c3p0-0.9.1.2.jar mysql-connector-java-5 ...

  9. [C++]数据结构:线性表之(单)链表

    一 (单)链表 ADT + Status InitList(LinkList &L) 初始化(单)链表 + void printList(LinkList L) 遍历(单)链表 + int L ...

  10. haproxy报错解决

    .有一次访问出现 错误 http://192.168.0.200:10080 haproxy service unavailable no server is avaible to handle th ...