(点击此处查看原题)

题意分析

  一共有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. JavaWeb_(SpringMVC框架)测试SpringMVC&Spring&MyBatis三大整合

    搭建 SpringMVC&Spring&MyBatis三大整合 传送门 1.准备 测试搭建S pringMVC&Spring&MyBatis三大整合 用例   a)准备 ...

  2. 【ElasticSearch+NetCore 第二篇】Nest封装

    using Elasticsearch.Net; using Nest; using System; using System.Collections.Generic; using System.Li ...

  3. [题解] [Code+#1]Yazid 的新生舞会

    题面 题解 upd : \(cnt_i\) 代表值为 \(i\) 的个数 我们可以暴力枚举众数 \(k\) 把等于 \(k\) 的赋值成 1 , 不等于 \(k\) 的赋值成 -1 这样原序列就变成了 ...

  4. 数据库隔离级别,每个级别会引发什么问题,mysql默认是哪个级别

    1.脏读  脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据. 当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的 ...

  5. Singleton模式(单例模式) 饿汉式和懒汉式

    目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的“皇帝”都是指叫的XXX本人; 常见单例模式类型: 饿汉式单例:直接将对 ...

  6. zabbix :web 界面显示的监控项值为0或者空

    [参考文章]:[错误汇总]zabbix_get 的值一直为 0 1. 问题现象 zabbix 版本:3.4: server 端部署在 192.168.145.134 ,agent 节点部署在 192. ...

  7. 《梁宁·产品思维30讲》课程学习笔记(内含全套音频+ppt资料

    科技进步.产品迭代.公司演化.组织变迁……不变的是用户的情绪和人性. 那些信奉“用户驱动”的人,从普通人变成了行业大佬,建立了自己的世界.乔布斯.马化腾.马云.雷军.张小龙.周鸿祎.傅盛……这些改变世 ...

  8. Qt:使用Model-View,动态的加载显示数据

    共有 main.cpp, Widget.h, Widget.cpp, Widget.ui, MyModel.h, MyModel.cpp 六个文件. 可从此下载整个工程文件: /Files/biao/ ...

  9. [dart学习]第六篇:流程控制语句

    经过前面的基础知识了解学习,我们今天可以进入语句模块啦. dart主要有以下流程控制语句: if-else for循环 while和do-while循环 break和continue switch-c ...

  10. TreeView如何实现选中的节点上移或下移 [问题点数:20分,结帖人nww2002]

    在TreeView中,如何实现选中一节点,右键点击上移或下移 TTreeNode.MoveTo() 一.获得Tree上的结点var NowNode : TTreeNode;begin  NowNode ...