CodeForces - 1251D (贪心+二分)

题意

https://vjudge.net/problem/CodeForces-1251D

您是一个大型企业的负责人。在您的企业当中共有n位员工为您工作,而且非常有趣的事是这个n是一个奇数(n不能被2整除)。

您必须给你的员工分配工资。最初,您有s美元,而第ii个员工应得的薪水应该是li?∼ri?之间的一个值。而无论怎么分配每个人的工资,您必须使得所有分配的工资的中位数最大。

对于一个长度为奇数的序列,如果要找到他的中位数,就需要先对这个序列进行排序,之后找到中间位置的数字。举例来说:

  • 序列[5,1,10,17,6]的中位数是6
  • 序列[1,2,1]的中位数是1

保证您有足够的钱来支付最低的工资,即l1?+l2?+?+ln?≤s。

注意,您不必把所有的钱都花在员工的开支上。

思路

假设符合要求的中位数为x,首先,按右端点从小到大排序,ri的中位数即是x的上界;按左端点排序,得到x的下界为li的中位数。这个很好理解,画个数轴,基本就是那回事。。然后我们在x的上下界里二分,check所花费用是否小于等于s即可。怎么check呢?考虑贪心,对于ri<x的数,我们就取li,这样可以腾出更多的资金;对于li>x的数,我们取li,也是为了腾出更多资金;对于li~ri穿插x的数,我们先丢一起。通过刚才的判断我们可以得到放到x左边和右边的个数,现在我们遍历穿插的数,如果当前x左边的个数小于右边,那么这个数得用来放到左边,用最小的li即可;否则放到右边,用x的值即可。最后还剩一个数,那就是中位数x啦,所以判断tmp+x<=s即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=200005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
struct node
{
    ll l,r;
} g[N];
int n;
ll s;
bool cmp1(node a,node b)
{
    return a.l<b.l;
}
bool cmp2(node a,node b)
{
    return a.r<b.r;
}
node gg[N];
bool check(ll x)
{
    ll tmp=0,l=0,r=0,cnt=0;

    for(int i=1; i<=n; i++)
    {
        if(g[i].l>x)
            tmp+=g[i].l,r++;
        else if(g[i].r<x)
        {
            tmp+=g[i].l,l++;
        }
        else
        {
            gg[cnt++]=g[i];
        }
    }
    int i=0,j=cnt-1;
    while(i<j)
    {
        if(l<r)
            tmp+=gg[i].l,l++,i++;
        else
            tmp+=x,r++,j--;
    }
   // cout<<"gg"<<endl;
    return tmp+x<=s;
}
int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        for(int i=1; i<=n; i++)
        {
            cin>>g[i].l>>g[i].r;
        }
        sort(g+1,g+1+n,cmp2);
        ll R=g[n/2+1].r;
        sort(g+1,g+1+n,cmp1);
        ll L=g[n/2+1].l;
        ll l=L,r=R,mid,ans=L;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid))
            {
                l=mid+1;
                ans=mid;
            }
            else
                r=mid-1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/mcq1999/p/11885700.html

时间: 2024-10-11 18:48:11

CodeForces - 1251D (贪心+二分)的相关文章

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebo

Card Game Cheater(贪心+二分匹配)

Card Game Cheater Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1566    Accepted Submission(s): 822 Problem Description Adam and Eve play a card game using a regular deck of 52 cards. The rule

CodeForces 424D: ...(二分)

题意:给出一个n*m的矩阵,内有一些数字.当你从一个方格走到另一个方格时,按这两个方格数字的大小,有(升,平,降)三种费用.你需要在矩阵中找到边长大于2的一个矩形,使得按这个矩形顺时针行走一圈的费用,与给定费用最接近.3<=n,m<=300. 思路:O(1)计算一个矩形的费用不是什么难事,因为考虑到有前缀性质(前缀性质:[l,r] = [0,r] - [0,l-1]),只要预处理好各行各个方向行走的费用,就容易计算. 直接枚举容易得到O(n^4)的算法.难以过.这时就应当想到优化.实际上,经过

Codeforces 460C prsent(二分答案)

//题意:给定N朵花的原先的高度,从左到右排列, //最多浇水m天,每天只能浇一次,每次使得连续的w朵花的高度增长1,问最后最矮的花的高度最高是多少. # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int main() { __int64 n,m,w,l,r,i,m1,sum; __int64 a[200010],b[200010]; while(~

贪心/二分查找 BestCoder Round #43 1002 pog loves szh II

题目传送门 1 /* 2 贪心/二分查找:首先对ai%=p,然后sort,这样的话就有序能使用二分查找.贪心的思想是每次找到一个aj使得和为p-1(如果有的话) 3 当然有可能两个数和超过p,那么an的值最优,每次还要和an比较 4 注意:不能选取两个相同的数 5 反思:比赛时想到了%p和sort,lower_bound,但是还是没有想到这个贪心方法保证得出最大值,还是题目做的少啊:( 6 */ 7 #include <cstdio> 8 #include <algorithm>

Codeforces 437D 贪心+并查集

这个题目让我想起了上次在湘潭赛的那道跪死了的题.也是最值问题,这个也是,有n个动物园 每个都有权值 然后被m条路径相连接,保证图是连通的,然后求所有的p[i][j]之和.i,j为任意两个zoo,pij就为i到j路上遇到的包括i j在内的最小权值的zoo 然后我就焦头烂额了一下,这个明显就是看某个最小值为最后的结果发挥了多少次作用,但这个是图,要知道某个节点到底给多少条路径贡献出了最小值,还真是有点没头绪(在已知的复杂度一看 最多只能用nlogn的),最后是看了解答才知道的 用并查集来解决某个最小

hdu 1969 Pie(贪心+二分查找)(简单)

Pie Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5628    Accepted Submission(s): 2184 Problem Description My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I

CodeForces 371C Hamburgers 二分

CodeForces 371C Hamburgers 二分 题意 给你一个做汉堡包的菜单,他们是由B S C,三种材料做成的,现在我们有一些材料和钱,我们想做最多的汉堡包,请问最多是多少? 解题思路 这里我们开始我们可能会想该怎么买,也就是买的策略是什么,其实我们可以不用去思考这个,理由如下: 假如我们知道最后的结果,我们是不是可以算出来我们要买的东西?答案是肯定的(在钱不浪费的情况下),再加上这个答案是线性单调的,也就是如果答案是m,那么小于m的也是一定可以做到的,这样我们就可以使用二分来枚举

Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)

题目链接: http://codeforces.com/problemset/problem/830/A 题意: n个人,k个钥匙(n<=k),p表示这些人要到达的位置 给出n个人的位置以及钥匙的位置,问花时间最多的那个人用时最少是多少?? 思路: 二分+贪心: 二分最少时间,需要对a,b位置数组排序,我们check函数只需要从左到右一个一个找过去,因为如果选后边的点,可能会使结果更差,假如当前这个人选后面的点,那可能会选中后面的人可以选的唯一的钥匙,不会使解更优. check(40)的时候答案