D. Salary Changing(找中位数)

题:https://codeforces.com/contest/1251/problem/D

题意:给你n个单位需要满足达到的区间,再给个s,s是要分配给n的单位的量,当然∑l<=s,问经过分配后能够达到的最大中位数是多少

题解:二分找中位数,成立原因:代码注释

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=b;i>=a;i--)
#define pb push_back
#define pll pair<ll,ll>

const int inf=0x3f3f3f3f;
const ll INF=1e18;
vector<pll>a;
int n;
ll s;
ll check(ll m){///挑出能达到中位数midd的都要达到中位数和已经比中位数大的数,且只能取一半+1个
///因为a 已经按照从大到小排序了,所以从前往后地挑出能达到midd的来加肯定是耗钱最少的
    int countt=a.size()/2+1;
    ll sum=0;
    for(int i=0;i<a.size();i++){
        if(a[i].first<=m&&a[i].second>=m&&countt){
            sum+=m;
            countt--;
        }
        else{
            sum+=a[i].first;
            if(a[i].first>m)
                countt--;
        }
    }
    if(countt)
        return s+10;//让这一步不合法
    else
        return sum;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%d%I64d",&n,&s);
        a.clear();
        fo(i,1,n){
            ll x,y;
            scanf("%I64d%I64d",&x,&y);
            a.pb(make_pair(x,y));
        }

        sort(a.begin(),a.end());
        reverse(a.begin(),a.end());
        ll l=a[a.size()/2].first+1,r=s;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(check(midd)<=s)
                l=midd+1;
            else
                r=midd-1;
        }
        printf("%I64d\n",l-1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/starve/p/11736067.html

时间: 2024-10-09 20:48:16

D. Salary Changing(找中位数)的相关文章

有序数组中找中位数

问题描述 给定两个有序数组,返回这两个数组的中位数.如果中位数有两个,则返回它们的平均值. e.g. [1, 3, 5]和[2, 4, 6]的中位数是3.5 解决思路 如果两个数组的长度之和为奇数,则中位数有一个:否则中位数为其中两个的平均值. 从两个数组中找第k个数,可以使用递归的思路. 程序 首先,写出在有序数组a和b中找到第k大的程序: 1. 利用归并排序中的merge数组方法,时间复杂度为O(k). public int findKthNaive(int[] a, int[] b, in

SGU 114. Telecasting station 三分or找中位数

题目链接点这儿 一開始想都没想...直接上了三分...结果...sample的答案不一样...可是过了...然后又看了看. . . 发现这不就是高中或者初中出过的求中位数的题么. . .直接找到这些的中位数即可了....假设某一点处人口不止一个.那就把它拆成一个一个的点. 然后求中位数. 嗯... 这题就结束了. . . 至于三分的过程,事实上就是二分略微改进的版本号.二分仅仅能求单调的函数,假设函数在定义域内不是单调的,那么二分就失效了.当然. ..这时能够用数学上的无穷分逼近,通过分成若干小

LeetCode Median of Two Sorted Arrays 找中位数(技巧)

题意: 给两个有序(升or降)的数组,求两个数组合并之后的中位数. 思路: 按照找第k大的思想,很巧妙.将问题的规模降低,对于每个子问题,k的规模至少减半. 考虑其中一个子问题,在两个有序数组中找第k大,我们的目的只是将k的规模减半而已,所以可以对比nums1[k/2]和nums2[k/2]的大小,假设nums1[k/2]<=nums2[k/2],那么nums1[0~k/2]这部分必定在0~k之中,那么将这部分删去,k减半,再递归处理.这里面可能有一些细节问题要考虑: 1. 如果其中1个数组的大

codeforces D Salary Changing

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

找中位数O(n)算法

题目描写叙述: 给定一个未排序的整数数组,找到当中位数. 中位数是排序后数组的中间值,假设数组的个数是偶数个.则返回排序后数组的第N/2个数. 例子 给出数组[4, 5, 1, 2, 3], 返回 3 给出数组[7, 9, 4, 5],返回 5 解题思路: 利用快排划分的思想,递归处理. 參考代码: <span style="font-size:18px;">public class Solution { public int median(int[] nums) { re

找中位数

题目描述 中位数定义:一组数据按从小到大的顺序依次排列,处在中间位置的一个数 (或最中间两个数据的平均数). 给出一组无序整数,求出中位数,如果求最 中间两个数的平均数,向下取整即可(不需要使用浮点数) 输入描述: 该程序包含多组测试数据,每一组测试数据的第一行为N,代表该组测试数据 包含的数据个数,1<=N<=10000. 接着N行为N个数据的输入,N=0时结束输入 输出描述: 输出中位数,每一组测试数据输出一行 #include <iostream> using namespa

Educational Codeforces Round 75 (Rated for Div. 2) D. Salary Changing

链接: https://codeforces.com/contest/1251/problem/D 题意: You are the head of a large enterprise. n people work at you, and n is odd (i.?e. n is not divisible by 2). You have to distribute salaries to your employees. Initially, you have s dollars for it,

二分题 D - Salary Changing codeforce

题意:给出n个人(n是奇数),s钱:s为总的可以付工钱的钱: 每一个工人有一个付工钱的区间,只要在这个区间范围内,随便一个数都可以当作给这个工人付了钱: 老板要付给每个工人钱,并且付钱的中位数要尽可能大: 问:最大的中位数是多少: 思路:贪心+思维+二分: 我们以中位数为主体进行二分.那么就需要n/2+1个大于等于中位数的数: 这个时候我们先给钱排序,按第一个数从大到小排: 然后check部分,从1到n遍历,如果满足x在区间范围内,就取x这个数: 那么,为什么就要取这个数呢,因为我们迟早要凑到n

Salary Changing CF-1251D(二分)

题意: 有$n$个员工,$s$元钱,现在要给每个员工发工资.每个员工的工资的范围$(l_i,r_i)$,求所有员工的工资中位数的最大值. 思路: 二分答案,$check$的时候判断工资可以大于等于$mid$的员工个数,用最小代价购买之后判断总价钱会不会超出范围. 代码: 1 //#include<bits/stdc++.h> 2 #include <set> 3 #include <map> 4 #include <stack> 5 #include <