(点击此处查看原题)

题意分析

  一共有s元钱,要用这些钱给n个人发工资,发给每个人的工资si有最少和最多限制 si ∈[li,ri],在发给n个人的总工资小于s的情况下,要求发给n个人中的工资的中位数最大,并求出这个最大的中位数(数据满足:∑li <= s )

解题思路

首先注意到发给n个人的工资的中位数mid和n个人所得总工资∑si 具有线性相关性,即 ∑si ∝ mid ,所以我们可以通过二分mid 求出求出满足条件的最优解

随后我们需要判断当前所得的中位数mid是否满足条件 ,显然,只要给至少n/2 + 1个人发的工资si >= mid ,并且∑si <= s ,则此mid满足条件

那么为了满足条件,我们会想着让更多的人发放的工资大于等于mid,同时∑si <= s,为此,我们这样设计判断函数check:

(1)预处理:因为每个人的工资至少有l[i] ,那么我们先为每个人分配最低工资l[i],求得余下总工资 s = s - ∑l[i]

(2)预处理:将n个人的工资按最低工资升序排序

(3)使用的变量:

  cnt:记录发放工资大于等于mid的总人数

  sum:记录剩余的用于发放的钱

(4)处理方法:对于当前发放工资的中位数mid,从最低工资大的人开始向最低工资小的人枚举

  1、若l[i] >= mid

    显然,给这个人发放l[i]的工资即可,cnt++

  2、若l[i] < mid <= r[i] && sum >= mid - l[i]

    cnt++,sum -= mid - l[i],表示将这个人的工资设置为mid,同时减去多给这个人的工资mid-l[i]

    此时会有个疑惑,即为什么发给这个人的不是最低工资?这是一种贪心的思想,因为我们将n个人按最低工资升序排序,同时反向枚举n个人,这样保证了先枚举到的人的mid-l[i]更小,也就是说,我们用最少的代价使得更多的人的工资大于等于mid,这样一来,最后只需要判断cnt 是否大于等于 n/2 + 1 即可

代码区

#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 = 4e5 + ; struct Salary
{
int l,r;
bool operator<(const Salary& s) const
{
return this->l < s.l;
}
}salary[Max]; int n;
ll s; bool check(ll mid)
{
int cnt = ;
ll sum = s;
for(int i = n ;i >= ; i --)
{
if(salary[i].l >= mid)
{
cnt++;
}
else if(salary[i].r >= mid && sum >= mid - salary[i].l)
// 为了让更多的人的工资大于mid,因此从最低工资大的人开始向前枚举,这样造成的额外工资最小,
// 即总发放的工资最小
{
cnt++;
sum -= mid - salary[i].l;
}
}
return cnt >= n/ + ;
} int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%lld",&n,&s);
for(int i = ;i<= n ;i ++)
{
scanf("%d%d",&salary[i].l,&salary[i].r);
s -= salary[i].l; //保证必定取下界
}
sort(salary+,salary++n);
ll l = salary[n/+].l,r = inf;
while(l <= r)
{
ll mid = (l + r)>>;
if(check(mid))
l = mid +;
else
r = mid -;
}
printf("%lld\n",r);
}
return ;
}

codeforces 1251D Salary Changing (二分+贪心)的更多相关文章

  1. Codeforces 1251D Salary Changing

    D. Salary Changing 大意: 有n个变量, 每个变量有一个取值区间, 要求给这n个变量赋值, 使得n个变量的和不超过S且中位数尽量大(n一定为奇数) 二分答案, 中位数大于等于mid就 ...

  2. codeforces 803D Magazine Ad(二分+贪心)

    Magazine Ad 题目链接:http://codeforces.com/contest/803/problem/D ——每天在线,欢迎留言谈论. 题目大意: 给你一个数字k,和一行字符 例: g ...

  3. Codeforces 1132D - Stressful Training - [二分+贪心+优先队列]

    题目链接:https://codeforces.com/contest/1132/problem/D 题意: 有 $n$ 个学生,他们的电脑有初始电量 $a[1 \sim n]$,他们的电脑每分钟会耗 ...

  4. CodeForces - 343C Read Time (二分+贪心)

    题意:有N个指针头,M个标记,用这N个针头扫描所有的标记,针头之间互不影响,求扫描完M个标记的最短时间 分析:二分搜答案,mid为时间限制,则只要所有的点在mid秒内被扫描到即可. 对于每个指针,若其 ...

  5. codeforces D Salary Changing

    题意:给你n个人,和s块钱,每个人都有一个工资区间,你给所有人都发工资.然后要他们工资的中位数最大. 思路:二分找那个值.那个值要满足至少有n/2+1个工资区间内. #include<cstdi ...

  6. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  7. 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心

    /** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...

  8. 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

    题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...

  9. codeforces Gym 100338E Numbers (贪心,实现)

    题目:http://codeforces.com/gym/100338/attachments 贪心,每次枚举10的i次幂,除k后取余数r在用k-r补在10的幂上作为候选答案. #include< ...

随机推荐

  1. Docker实践--搭建Yapi测试平台

    背景:项目需要选择不同测试平台,筛选一个最佳平台 现状:一台机器安装多套环境,虚拟机太繁琐 解决方案:通过Docker模拟安装测环境 参考:https://blog.csdn.net/qq_32447 ...

  2. sed基础

    sed  文本流编辑的  行编辑器 hold space :保持空间.仓库,半成品 一次从文件中读取一行,放到自己编辑的内存缓冲空间即模式空间,不会编辑原文件:根据所给定的命令在模式空间中做编辑处理, ...

  3. 关于在eclipse中Undefined attribute name (role).解决办法

    方案一: 只需要在jsp表头添加一句: <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c&q ...

  4. spring boot + swagger2

    spring boot集成swagger2:     swagger2是一个基于restful的开源设计,构建,文档,访问的开源工具集.开发中它的在线可视化文档功能,可以动态生成文档,简化前后对接工作 ...

  5. 5.3.4 Hadoop序列化框架

    序列化框架 除了writable实现序列化之外,只要实现让类型和二进制流相互转换,都可以作为hadoop的序列化类型,为此Hadoop提供了一个序列化框架接口,他们在org.apache.hadoop ...

  6. Leetcode题目287.寻找重复数(中等)

    题目描述: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...

  7. cmder的segmentation fault错误修复

    Segmentation fault 现场还原 问题出现的原因是我在 cmder的命令行里执行了cmder /register ALL命令,本意是把cmder放到右键菜单里去的 但我没想到的是,各种不 ...

  8. js生成带log的二维码(qrcodejs)

    github: qrcodejs cdn: http://static.runoob.com/assets/qrcode/qrcode.min.js #qrcode #qrcode margin: 2 ...

  9. .NET 5 = .NET Core vNext

    Introducing .NET 5 .NET 5 = .NET Core vNext .NET 5 is the next step forward with .NET Core. The proj ...

  10. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_6.RabbitMQ研究-入门程序-消费者

    我们在consumer这个功能下进行代码的编写 首先是新建这个层级的包 创建入门程序的消费者 消费者也需要和mq建立通道.建立连接创建通道 在顶部都声明这个队列 下面写核心代码监听队列.basicCo ...