(点击此处查看原题)

题意分析

  一共有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. 【新词发现】基于SNS的文本数据挖掘、短语挖掘

    互联网时代的社会语言学:基于SNS的文本数据挖掘 python实现 https://github.com/jtyoui/Jtyoui/tree/master/jtyoui/word  这是一个无监督训 ...

  2. 数据结构实验之二叉树三:统计叶子数 SDUT 3342

    #include <stdio.h> #include <string.h> struct node { char data; struct node *l,*r; }; st ...

  3. css偷懒神奇

    偷懒神奇链接:https://qishaoxuan.github.io/css_tricks/glass/

  4. C#连接数据库时connectionStrings配置

    <connectionStrings> <add name="ConnectionStringName" connectionString="Data ...

  5. Python学习日记(四)——Python基本数据类型梳理(int、str、list、tuple、dict)

    数字(int) 1.创建方式 n1 = 123 n2 = int(123) 2.内存分配 #共同用一个内存地址的情况 n1 = 123 n2 = n1 #用两个内存地址的情况 n1 = 123 n2 ...

  6. XXE外部实体注入漏洞——PHP

    前言 XXE Injection即XML External Entity Injection,也就是XML外部实体注入攻击.漏洞是在对非安全的外部实体数据进行处理时引发的安全问题. 在XML1.0标准 ...

  7. POI的XWPFTableCell的方法

    1. XWPFParagraph addParagraph() 在这个表格单元格中添加一个段落 2. void addParagraph(XWPFParagraph p) 给这个表格加一段 3. ja ...

  8. 异步机制 - Overlapped

    1 前面说到 GetOverlappedResult的bWait含义 GetOverlappedResult的bWait含义表示是否需要等待,如果IO还处于PENDING状态,内部大概实现是这样 hO ...

  9. Java-基于 Instrument 的 Agent

    Agent 为 JVMTI 的客户端. 这里记录的是基于Java Instrument 的 Agent 实现,还有直接基于 JVMTI 的 Agent 实现. 在 JDK1.5 以后,我们可以使用 A ...

  10. Flutter移动电商实战 --(38)路由_Fluro中Handler编写方法

    在main.dart中初始化Fluro 编写handler 在lib下新建routers文件夹,表示里面要很多路由相关的文件 我们声明一个Handler,在里面handlerFunc固定的两个参数 重 ...